|
|
原文:http://www.vckbase.com/document/viewdoc/?id=1911: t" N$ J" Z5 Q$ z
$ S6 F5 z# v8 P: C; D( K
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。
# B7 Q. F1 N& I! L3 P- C- [对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下: " u+ _# t' \( r; @& p
- typedef /* [wire_marshal] */ OLECHAR *BSTR;
. A$ }) X' p4 a! }- T9 T - typedef WCHAR OLECHAR;1 l% X7 W) ^. J" v
- 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);
2 w( u* ~2 _$ G2 _ - INT SysReAllocString(BSTR* pbstr,const OLECHAR* psz);6 q5 [- ?, N" Z! [1 A. T. W6 T
- BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
; k& t, D4 U4 [% x! I \ - INT SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
( {5 o; ^% ]6 V' e - void SysFreeString(BSTR bstrString);
; {" M4 O4 e& Q2 H! }9 N - UINT SysStringLen(BSTR);
( e! u6 ~6 E8 H! W) O9 _+ n - UINT SysStringByteLen(BSTR bstr);
3 e7 t2 Q6 m# C+ k, ?6 g - BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码 下面对上述API用法进行说明。! f6 k2 m! p* _
8 K$ m% X9 v( S( r* L1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:0 k2 U2 C) S w6 E& X0 f
7 D4 w1 ^9 i4 @6 |
printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));9 o6 u" b( [4 g4 d
4 T- A% ?% I0 n! L# b- Y. j语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句
, x. }1 s; f+ g0 Q0 Q" t4 L4 a- P& |8 X- y3 r$ M
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));
. G+ d" w0 y; r0 `& U( A, t% k: z# H Z5 `
输出的是“c”是语句中的第一个字符,语句
; t2 U; v, [. \8 j$ R/ U0 w1 [6 ^' J% t+ J
printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));* r3 N5 ~5 Z+ t. _$ ]
$ w- l2 K R- g; `输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
$ x; o9 |2 I |2 z4 X* Y P2 r* y. C2 q ?
2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:
R( T) G$ R2 {- G4 Y' F: r) {- BSTR bstr=SysAllocString(L"create bstr string");
3 |! R% J# n( h1 B/ f' g# N2 | - SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
# b% l# Y" X( ]5 d+ w - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));2 Y: u' x' j. S! b( u8 ]
- 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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。 8 E/ f( j# r0 j5 z8 h
- SysReAllocString (&bstr,L"new string new string"); . f. p2 J0 j h5 [" y
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
$ j; F/ S0 O" Y" C. u' A; l - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));) Y& `# D/ q' g6 Z, b2 S
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:2 S1 @$ d2 d* e$ U5 p* K& m
- BSTR bstr=SysAllocStringLen(L"create bstr string",6); 9 {, G; l, F) C, P& C! n7 g
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); 8 }4 y* i1 |2 D
- 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串。
) l3 N4 K7 n; @0 T/ Q+ D! k! C$ t4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如:
* c4 X8 p7 i8 d) y% x- BSTR bstr=SysAllocString(L"create bstr string"); - g0 N4 r, {& a) b% k
- SysReAllocStringLen(&bstr,L"new string",3);5 f0 S4 ?$ l: [. m3 P. v8 }* p" J: B2 i
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
( f% G) B$ h" k6 |) f; k, z - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
. x$ }9 z( p/ e2 I1 W6 D - printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: 6 V2 r- [! E& d/ L6 g, D" g
6、SysStringLen求一个BSTR字符串的长度,如:
0 R2 j9 ^9 x7 f- printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码 7、SysStringByteLen求一个BSTR字符串的字节长度,如:$ x& `" c y: j3 q( j6 b6 M- o
- printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码 8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。
+ I- H0 I7 `/ f以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。
1 i& I$ @; }1 C# L9 @, [CComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。
) w N4 L* b {1、构造一个CComBSTR对象
6 V+ Z/ n# Y0 C: ? [& V7 ?
! F7 ]& D0 @/ f; U# W& C8 }- CComBSTR bstr1;
$ r M. L W- h7 ?( i) ? - MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象
4 B2 |8 U/ b" l9 {$ ?' K8 k - 8 G5 ]4 {! V9 }& k: _$ B
- CComBSTR bstr2(L"this is a BSTR string");
- | g7 {! X8 i+ i7 V* n N8 H( L - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象9 X5 y. N7 m+ b6 ]+ ?
- 8 p0 l1 Q5 H7 x \+ g0 F
- CComBSTR bstr3(5);/ z. p( n% x+ r/ Z
- MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。
" W3 b% Q% B5 C - 2 J2 r" y N& A6 u
- CComBSTR bstr4(3,L"this is a BSTR string");
0 R1 y4 r3 ^7 X - MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码 我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:$ m; t0 _& |2 _9 L/ U2 |3 X( s! E
- CComBSTR bstr1(L"this is a BSTR string");
' S0 w- a; A) W6 S" I' b+ v - CComBSTR bstr2(bstr1);
! W1 e) t& m' D1 Z8 o - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码 最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
, o6 q5 ?$ n0 W- static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};
$ A1 y3 a. V1 L8 F5 E4 b* Z+ o9 N& ]% z: g - CComBSTR bstr1(GUID_Sample);& j" e5 X* N# N9 K
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码 2、CComBSTR定义的常用操作如下
! ]# ^! f, d3 @; H7 d4 ~( H% s(1)“=”操作符(赋值操作),如:
5 w V2 _6 {3 M( R$ o8 h7 P" z* b/ z- CComBSTR bstr1(L"this is a BSTR string");
$ C1 V# Y3 L& |# o1 u - CComBSTR bstr2=bstr1;7 E) T2 {# ^! ?/ J+ E
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码 (2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:+ X/ @& ^/ f, o/ I# Q2 C
- CComBSTR bstr1(L"this is a BSTR string");# J4 O( b! W4 a( |+ {
- BSTR bstr2=bstr1;0 |0 w# Y! t( y9 L3 U0 M
- MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
: B" g& q( b) H, } - 1 c. ]9 V9 L- x
- CComBSTR bstr1(L"this is a BSTR string");
$ U% M1 g) \ O/ [1 \ - MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码 (3)!= 操作符,用来直接比较两个CComBSTR对象,如: v) t# Z: d$ @/ p" z
- CComBSTR bstr1(L"this is a BSTR string1");; E# W( Z6 z2 C" \) n, J
- CComBSTR bstr2(L"this is a BSTR string2");
* {5 _1 W0 C( ^/ V) @- n - if (bstr1!=bstr2){/ H' l5 c8 G; x! N% O: m+ ^' n5 c
- MessageBox(NULL,L"true",L"BSTR test",MB_OK);
3 M# ^$ J% F9 A/ e+ n7 z0 H - }
2 `0 V) Q v! _8 m% }: ? - else
+ Y+ b8 I, e6 N* c - {; B" C7 Z# r, G, W2 w# o: j
- MessageBox(NULL,L"false",L"BSTR
, g/ `, |5 L& b, Z; G( {/ a- G - test",MB_OK);: ^$ ~% ^, s3 {4 c5 |9 L
- }
复制代码 3、CComBSTR定义的常用方法如下
( ~/ K4 q1 F0 l3 |$ l, b! h; k( d(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:7 X, O9 Z4 ]# C& Z/ O4 i6 Y: @
- CComBSTR bstr1(L"this is a BSTR string1");
* k, P' L5 ^$ q - BSTR bstr2=bstr1.Copy ();; m9 |2 z/ r3 u s9 ?
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
. q) J z, B c- CComBSTR bstr1(L"this is a BSTR string1");' k8 Q1 `+ e7 U: @0 N5 O7 \
- BSTR bstr2;
+ s: ]5 q9 z( _' C" {+ T$ a. Z - bstr1.CopyTo(&bstr2);! l: U9 j7 E+ y4 j3 C# U& S# ?
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
% Z$ e; h- K) D; K# i* ]. b- BSTR bstr1=::SysAllocString (L"this is a BSTR string");* T7 o3 a0 M; x" L4 c
- CComBSTR bstr2;- x/ l6 O& p; Z7 j: [6 b
- bstr2.Attach(bstr1);
) [& O" J V; G+ n3 t7 e - MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码 (4)Detach方法分离BSTR字串与CComBSTR对象,用法:
" k- S$ J/ e1 J+ _/ n7 p: A- ^(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。' ?+ F. A/ A& T C
) N( W0 _% x% m8 r; b. ] q8 y |
|