|
|
原文:http://www.vckbase.com/document/viewdoc/?id=1911 H* Z1 l+ ~4 F5 r0 ~; @
% T9 r# K n, w$ q! @$ k8 q* _
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。 / _4 ?7 r) _5 j6 ?8 d% X
对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下: , ]' Q( T# `/ X" l6 C
- typedef /* [wire_marshal] */ OLECHAR *BSTR;! `+ b+ K: Q+ ?; ~6 H/ R
- typedef WCHAR OLECHAR;
7 y9 Z4 t6 H/ ^3 X+ [) {( ? - typedef wchar_t WCHAR;
复制代码 由于COM是跨系统及不同开发语言间实现互操作的技术,常规以Null结尾的简单字符串在COM 组件间传递不太方便。因此,便出现了BSTR字符串类型,BSTR是指针类型,标准BSTR是一个有长度前缀和null结束符的OLECHAR数组。BSTR的前4字节是一个表示字符串长度的前缀。BSTR长度域的值是字符串的字节数,但不包括字符串结束符。 BSTR实际上包含的是Unicode串,所以字符数是字节数的一半。这种方式的优点是允许程序员在BSTR串中间嵌入NULL字符,字符串的长度由BSTR的前四个字节表示,(长度中可能包含NULL),bstr字符串是不能象基本数据类型一样直接进行定义的。为处理BSTR字符串,微软在OleAuto.h中定义了BSTR API,分别是:- BSTR SysAllocString(const OLECHAR * psz);/ {" \9 ]# x7 k% t% Q
- INT SysReAllocString(BSTR* pbstr,const OLECHAR* psz);' F1 U* N7 }9 {! i# X, a) Z) g1 g
- BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);% f8 |1 |$ \5 a) M
- INT SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
& a- D5 Q* S+ Z& M1 W) a, n - void SysFreeString(BSTR bstrString);
1 N6 F: t8 Q$ S4 s$ J5 T% { \8 d1 D, G* ? - UINT SysStringLen(BSTR);, n3 a& ~: Z8 P% E& e9 d
- UINT SysStringByteLen(BSTR bstr);/ B) O7 _+ ?# K9 ~8 y7 R
- BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码 下面对上述API用法进行说明。* t: ]) }' L0 D( `8 i, y
/ ]! e0 e; o$ [; y. ?1 T+ }! e- _
1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:$ D3 H% f5 p8 G/ T6 D. Z
$ D+ L% C7 I* K7 c" X6 F
printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));
: _+ k9 s. s% y1 D; `6 t5 |; g0 ?4 u( K: \+ q
语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句4 m/ M" M( D% ~6 w5 M) R, u
7 T, _4 e7 L1 h
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));/ z! w0 j0 U( b! ~0 Z
, Y% ]1 ?) k/ c& r: |输出的是“c”是语句中的第一个字符,语句
. W! v! Q) e3 c9 P. S9 M+ K5 l( O# ]3 {8 S
printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));, Z9 Z: z3 |6 V2 k. N) @' U
! |4 W5 w- E I输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
( j3 Z8 [9 k- k- ?: U9 n0 I5 f \! M8 A/ @7 a. _
2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:* J9 | ]8 U8 d! X$ r- }
- BSTR bstr=SysAllocString(L"create bstr string"); 2 r2 h8 ^/ t- T! _
- SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
% I/ [/ Z8 U& |* u* P9 T% Y - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));, B6 F" z6 r9 B7 Q- s- b; j
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 该语句最后输出是“14,n,g”说明SysReAllocString (&bstr,L"new string");语句是在已经生成的bstr字符串上建立一个新的字符串,因新串“new string”的长度是20,换算成16进制正好是14,而输出的g说明因新串短于旧串所以原字符串超出的部分为变化,但已经超出14所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。 ! r- O$ f* ?' }* O& W
- SysReAllocString (&bstr,L"new string new string"); 0 Z8 J4 r( b9 W5 w
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
. X R; p) G* p! ?6 o, g a - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
9 u2 n% s8 g9 I' x - printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:
! z b' ^) b0 N" Z- BSTR bstr=SysAllocStringLen(L"create bstr string",6); ) V0 w9 s+ m+ L2 H# F. G, [
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); 5 _, c: u& m% J8 ?+ _ H8 O
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 虽然“create bstr string”的长度是18个字符但此语句只分派6个字符的BSTR串。
' t7 w4 ?% U+ p' b( Y. X% I4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如:
" ~3 u" r9 K/ Z8 Y: k4 U- BSTR bstr=SysAllocString(L"create bstr string"); / T8 [ N1 s; Q& f3 j: ?3 Z5 d0 N
- SysReAllocStringLen(&bstr,L"new string",3);
+ u4 i" j0 ` h' n* V - printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
) z3 `* s% ^' R" c0 o, \ - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
; I* n3 T- l: [" q# T' I# s" r6 d - printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如:
2 @+ s% ~% e, u9 @6、SysStringLen求一个BSTR字符串的长度,如:4 u9 b2 H+ X- w1 S5 f9 e+ M; A
- printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码 7、SysStringByteLen求一个BSTR字符串的字节长度,如:
0 ^% |3 g4 N) @9 n; c: f- printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码 8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。5 a- G! x1 Z9 `) B
以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。) H2 i2 | _# }5 f: d y& h$ O. r
CComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。# ^9 j6 p8 T# ~% ]+ T3 u) C
1、构造一个CComBSTR对象
+ m+ N6 J7 s, E) S* [# k; b) j
: @2 n) l0 n9 Q- CComBSTR bstr1;# x1 e+ Y7 N; g% N8 L% }! C; s
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象 z- w- x) z7 z/ @* p: ?: N
- : E) b# j1 n3 {. u% T% Q
- CComBSTR bstr2(L"this is a BSTR string");
! {; }$ m {' S G$ X6 ^6 X# R - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象( e* r" g" i8 I
- * U. c# o' o0 Y9 L q2 `$ K
- CComBSTR bstr3(5);
' r. W A# O/ n+ f. B - MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。: V' Y; e* b9 _! P
- . ?0 J u- ]$ i, m& [
- CComBSTR bstr4(3,L"this is a BSTR string");
# V: }3 {4 Q( O1 D1 S8 K - MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码 我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:
# ?# ~) q F( S0 V1 F# V( |$ u- CComBSTR bstr1(L"this is a BSTR string");2 [( x- N7 Y Q6 a6 e
- CComBSTR bstr2(bstr1);) Y2 n, z0 H( z# t+ {6 Q
- MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码 最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如: / @, n- a8 O r1 H& n& O' J
- static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};* g' f$ l/ O. o/ R$ w; }) T
- CComBSTR bstr1(GUID_Sample);- i1 @( K. W- N0 {, c# E, I* u( g
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码 2、CComBSTR定义的常用操作如下: v* I6 f7 X8 {' R* M* L
(1)“=”操作符(赋值操作),如:9 B# ~2 n+ |6 p5 Z
- CComBSTR bstr1(L"this is a BSTR string");1 \( K u" ]+ f5 b' _4 ~
- CComBSTR bstr2=bstr1;) ~$ |& r6 N) E' U" H1 N
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码 (2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:
0 d+ n" g' |. Q- T5 a6 {3 W+ S- CComBSTR bstr1(L"this is a BSTR string");
# I6 l% P$ M( w0 \% f% B - BSTR bstr2=bstr1;5 A, b0 j; D: i; e/ N1 X
- MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换7 l" z' [8 F: \ N) e) Y* b4 O
- . Y9 N* N& f' }( w
- CComBSTR bstr1(L"this is a BSTR string");1 _* t6 v2 G- d% z8 B) _4 [
- MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码 (3)!= 操作符,用来直接比较两个CComBSTR对象,如:
7 U% N' Z, O- t0 F& o' X- CComBSTR bstr1(L"this is a BSTR string1");9 f0 R# g0 K% ?# e0 u0 M
- CComBSTR bstr2(L"this is a BSTR string2");; {9 N; y9 }4 ]4 |4 ]# b3 t( o( ~
- if (bstr1!=bstr2){9 K3 P/ L' }% w0 l+ K
- MessageBox(NULL,L"true",L"BSTR test",MB_OK);' m4 ^& _3 c: M* D! L$ ?
- }1 P) u) z; b9 O: t& a; ^
- else: c/ C4 v- G- K7 _8 j6 Z/ Y' A, q
- {
4 t1 J0 J; d' ?; L8 T - MessageBox(NULL,L"false",L"BSTR
# K1 S- E; {3 W o - test",MB_OK);
) e$ R5 k& e1 ]! Q - }
复制代码 3、CComBSTR定义的常用方法如下
' r* a ~# X" [3 v(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:
$ e& X+ `. {* \# `/ O( s1 s- CComBSTR bstr1(L"this is a BSTR string1");
$ R" r8 ~" t7 V% X' z - BSTR bstr2=bstr1.Copy ();# |; s: F( Q0 R# Y
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
0 b2 E2 `3 O3 w4 E, } v- CComBSTR bstr1(L"this is a BSTR string1");
- C: l& A3 D1 g$ ? K - BSTR bstr2;
. n7 a+ v5 U2 D3 y+ _" K - bstr1.CopyTo(&bstr2);
2 U0 g2 H9 M1 T7 j* f: J - MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
: `7 x, _! K% \, Y- BSTR bstr1=::SysAllocString (L"this is a BSTR string");9 h- q* {" n3 P+ N6 r# m% i$ w
- CComBSTR bstr2;4 v" v( l; c0 i7 b
- bstr2.Attach(bstr1);
$ O: m' D- m4 V4 I" i' k- x - MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码 (4)Detach方法分离BSTR字串与CComBSTR对象,用法:3 l, m/ {; }2 m# m5 n, |( t
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。
8 Y( ~" f! O8 S1 \- l4 `( W( O
8 t% |. v+ d8 ^" S* j% X5 K |
|