|
|
原文:http://www.vckbase.com/document/viewdoc/?id=1911! q) o! ~* k. h1 ^9 X+ H
1 H) T: U6 J5 d' _$ {$ X9 R9 [
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。
7 }3 o+ x0 u4 m' W1 c9 Z( y对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下: + ?9 e5 e. J3 U" X! N0 b8 d
- typedef /* [wire_marshal] */ OLECHAR *BSTR;+ {2 T3 ?; ]( W2 Z
- typedef WCHAR OLECHAR;0 \ T4 S; f9 w) m' M1 F2 f
- 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);$ z2 Q9 o# O# Z0 |8 _" P
- INT SysReAllocString(BSTR* pbstr,const OLECHAR* psz);7 _8 S5 h9 P' | {/ c7 g! }& Y7 C& [! l
- BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
( M: l+ `* J+ j i6 B- N# U - INT SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);% q3 m+ m. E/ {8 m! M8 F+ u
- void SysFreeString(BSTR bstrString);! r3 P, D" ?- {
- UINT SysStringLen(BSTR);
/ T/ f/ }' {8 b; b6 f; K# o3 q5 L - UINT SysStringByteLen(BSTR bstr);
4 P6 F! G% E: n( l - BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码 下面对上述API用法进行说明。, y# ]# J3 u& P4 f- m6 j
! ]0 w0 t4 R8 L( {1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:; C2 n* L( I) ^! b( s
$ i5 H! D6 P2 U- r# o& W- b8 ~0 qprintf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));4 d5 @ h8 w" s* o. R/ a& `& \
3 r1 Z. ^! b, p1 t9 h0 F5 `语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句
* o, y1 H% Q, P# a' t0 g7 [0 l( b" c7 J+ b* R t
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));
+ Q3 d. r+ K# m/ S$ N3 P5 ?' D- i D0 e8 h$ a
输出的是“c”是语句中的第一个字符,语句. b4 L" p+ m; Y. h2 U9 n( D
% o2 |4 h% B/ q& Iprintf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));0 B3 p H+ O0 }: r( i: P
: g% B I( s& D- W* N! `输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
: @4 ^: h# J/ w2 D* W& Q. o' M- J0 J/ B: }: W' g
2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:
@8 Y! @) j r+ C0 L- BSTR bstr=SysAllocString(L"create bstr string"); % c, u' t; x# D [2 [9 W) `) N
- SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
- D' p4 P( d$ v3 R - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));, |( P) ^: Y) [
- 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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。
Z) g" J& ^" n$ y( E- SysReAllocString (&bstr,L"new string new string");
% F. r$ e. V- j" Q7 L' |- _ - printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); ) ^6 G# W! K) b% a
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
2 i1 {5 w) t/ s! W0 l+ `" ] - printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:
n0 D" u. w% H7 N# K- BSTR bstr=SysAllocStringLen(L"create bstr string",6); 5 b$ y% |- I. S# y% t
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); a8 \8 G; _" S* w; @2 s& X
- 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串。5 a; \' W0 \3 o$ P& _7 w2 R
4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: * j. J* o1 k v) s
- BSTR bstr=SysAllocString(L"create bstr string"); ( L8 K6 P% c* J% c
- SysReAllocStringLen(&bstr,L"new string",3);
$ Q4 j- D- U3 m; X, O3 l - printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));7 W- b6 F+ _% ^; B7 w* I7 m/ a
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));# C' s( V$ h$ y4 f- Q" T" w
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: % g3 G( i, b3 T+ @" S* `
6、SysStringLen求一个BSTR字符串的长度,如:
( U9 v# }8 \" q& C. {* h h- printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码 7、SysStringByteLen求一个BSTR字符串的字节长度,如:6 [" Z4 c* u& N5 t
- printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码 8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。. ]# Y6 W" U( C+ O( ~1 C
以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。, z# `' e2 A7 s1 {7 G7 `3 ?1 e
CComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。* Q9 r1 X/ l4 B) K" s) M; Q4 D
1、构造一个CComBSTR对象* c/ l G6 {+ o. m ]
3 Q6 ]8 H+ n' T$ D- CComBSTR bstr1;
2 T/ R0 x0 B$ q* g7 f" r - MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象
; _/ B1 f, m: B" V
~5 a0 J- N! t# c5 p& b* S3 A- CComBSTR bstr2(L"this is a BSTR string");
0 @4 P7 {! ~0 ^( g6 o - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象
& ]; {7 w& H: E! j6 N) G1 q& e# | - + h: s2 y% ?; {3 O3 Z
- CComBSTR bstr3(5);
# z, J: g" i4 @ - MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。2 d$ M' }# C2 S: G2 [3 j
! Q3 M# s6 P. j6 O, S. i- CComBSTR bstr4(3,L"this is a BSTR string");+ s$ h6 f- k- g; a9 }1 n
- MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码 我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如: Z! U2 T2 r4 l! I0 i5 }5 i Z, Z
- CComBSTR bstr1(L"this is a BSTR string");
: I! z# c8 e2 z/ w - CComBSTR bstr2(bstr1);
0 \" w- Q9 H. E" j# F" A, h - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码 最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
; W* A" G8 I% p( d; ^( T9 e& q4 @/ z- static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};9 b) S8 \1 O7 [2 ]* i! D* p r1 g
- CComBSTR bstr1(GUID_Sample);
) w( I) _7 }. C9 c4 u7 ^ - MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码 2、CComBSTR定义的常用操作如下
6 S* S q# w5 n7 \(1)“=”操作符(赋值操作),如:
% V4 t1 e. }; v! A* p% K7 |7 X- CComBSTR bstr1(L"this is a BSTR string");4 k* R" L! m! `
- CComBSTR bstr2=bstr1;
3 f( ^' K- e7 R% _( k1 f - MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码 (2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:
* X' X! g9 `: s% \- V/ f- CComBSTR bstr1(L"this is a BSTR string");4 W1 r: U# s/ r4 {! K& w
- BSTR bstr2=bstr1;
. U; N1 V- |& Z- @) O3 g0 m - MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
" k% o5 ]! v- z' M - 3 B( Q0 w, [+ h1 p
- CComBSTR bstr1(L"this is a BSTR string");$ h$ Q$ Y y/ n m( a. Y8 l4 `
- MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码 (3)!= 操作符,用来直接比较两个CComBSTR对象,如:3 P! h7 z! O* V" j4 C
- CComBSTR bstr1(L"this is a BSTR string1");
! O W, d' Z# R' n, H& C - CComBSTR bstr2(L"this is a BSTR string2");
. t6 x* t1 O' o - if (bstr1!=bstr2){
' R" `$ R/ f% g7 K! e! n - MessageBox(NULL,L"true",L"BSTR test",MB_OK);8 z* X% d3 L: E* @3 W6 O0 Z, m! M
- }
3 i$ [4 B7 v5 L4 s3 S5 h8 } - else
/ G1 F( R `" g3 M2 }0 t - {/ ^9 ~! J3 h% u0 A
- MessageBox(NULL,L"false",L"BSTR 4 x6 Q* F9 a# P5 [( h, A8 a% y
- test",MB_OK);
- r$ U0 n2 @" t* A3 ]) g - }
复制代码 3、CComBSTR定义的常用方法如下 f& a+ L# k/ x m
(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:- T, D4 M- ]5 Z* X
- CComBSTR bstr1(L"this is a BSTR string1");' ]8 e) }1 f' \( s; ]5 i7 t
- BSTR bstr2=bstr1.Copy ();
* @' z+ S# F8 u5 b - MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如: 3 |* N: c7 _! L6 d) g
- CComBSTR bstr1(L"this is a BSTR string1");3 T) J3 L- D$ x) o) ~
- BSTR bstr2;' f9 w6 o8 M1 b# i. k, ^: P
- bstr1.CopyTo(&bstr2);+ B5 `# U5 R& E: B8 y N. k
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
% U0 \6 }: d! I- d6 }0 s1 R, i- BSTR bstr1=::SysAllocString (L"this is a BSTR string");
- x0 \( t, l4 Y& @4 Q3 b8 _ - CComBSTR bstr2;
) p: h7 o& o. c& r4 e: ? - bstr2.Attach(bstr1);. Q3 j' Y. u9 F7 F9 i
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码 (4)Detach方法分离BSTR字串与CComBSTR对象,用法:8 T+ \( J8 h! r' M* Y! c
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。4 W4 K+ T. S, M# }0 k$ H; _, i
]- g7 S% J, \6 E* M! o+ i2 S- S |
|