|
|
原文:http://www.vckbase.com/document/viewdoc/?id=1911
6 y# p% e' h7 D/ t9 K$ H' w- h. P& I$ F" z- K. |7 B6 U2 J
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。 5 |0 x( A. k3 N4 i* g, d2 Q7 [
对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下: 0 M' K+ C) J/ U' _2 A
- typedef /* [wire_marshal] */ OLECHAR *BSTR;/ W% e/ A. [& }2 e8 f) o4 {
- typedef WCHAR OLECHAR;' m$ k) Z: O( 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);4 s- k& f, a8 ]/ ]
- INT SysReAllocString(BSTR* pbstr,const OLECHAR* psz);0 b: Q' g3 T0 H& I/ Z# k. G
- BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
, H+ l; s& Y% X# n% Z: n0 M5 N# f( X - INT SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);; b% p- a% u, W8 v# a' l
- void SysFreeString(BSTR bstrString);; P# H8 @$ ?+ e# q: G
- UINT SysStringLen(BSTR);
+ K, g; D" T2 x7 d! C& C - UINT SysStringByteLen(BSTR bstr);' j+ `" f: t2 R$ w7 O; [
- BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码 下面对上述API用法进行说明。
7 q2 c ^! J! x* L1 u
- v/ D0 J( c4 v" T s' y1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:
; N; G+ Y! t1 W3 m% D/ ]* [
. i1 I5 }- ?- P) ^printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));5 M* D' W9 i1 L) Y/ A! H4 B( p
9 K2 d) X. ]$ H; c4 {语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句& i" k8 \: y& J* a. u
, u5 u5 e# U8 Y# F) Dprintf("bstr front 0 byte is %c",*((int*)((int*)bstr)));
& l8 p! w# W8 {4 r% a2 S
8 E1 T9 E% x9 o, O& ?输出的是“c”是语句中的第一个字符,语句- G9 E p- b. f# C9 g( _6 Q
5 o+ x2 b8 L. u) l/ p2 pprintf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));9 U! d; Q% Q, R7 f, d0 U# N
3 M2 z- d9 t, }- A& R+ U$ u输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
4 N Z% D8 b2 {) {: n
" @# x1 I6 S- I. X2 R) p8 D2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:: Y6 J3 o& H- ? v# u8 c
- BSTR bstr=SysAllocString(L"create bstr string");
d& q9 V9 {& u Z2 i - SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));6 n c* _/ U: @6 B
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));1 z$ X# L$ B) M% v% {
- 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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。
. }* q- G0 X$ }. P6 e1 w/ `- SysReAllocString (&bstr,L"new string new string"); 2 ]+ U: m, S& ~/ f8 E7 d
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); - e* c, Q! m+ F: ~5 @6 l! ?
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr))); \9 x, B: V- |' j( e/ D
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:( @0 v8 z' u ?) r% C R; F
- BSTR bstr=SysAllocStringLen(L"create bstr string",6); # n! Z ~; i% N7 M6 H: x+ u3 J7 z5 j3 K
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1)))); 8 Q( w9 E4 V( K
- 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串。
( y, Z$ X. h W$ C: C2 I4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如:
8 b3 R+ n' T! c' }1 v- BSTR bstr=SysAllocString(L"create bstr string"); 6 y7 I9 _/ j6 l; ?- E! k8 I
- SysReAllocStringLen(&bstr,L"new string",3);) U- ^, O& |$ y2 t9 G1 D- H# ]
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
0 u% u+ I# k, g& A( w - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));) w; \) S9 D5 x- Q
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: 0 r6 C$ S( l* u# l# }
6、SysStringLen求一个BSTR字符串的长度,如:
& }: V# n, ]$ @0 V5 `4 z# h6 ]- printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码 7、SysStringByteLen求一个BSTR字符串的字节长度,如:
% U! i* r. D$ s7 o- printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码 8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。8 Q( M, P4 B t5 D& Y$ L5 ~
以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。
1 \" }$ G/ O, o3 T& Y3 ECComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。0 g* T# }% k% P( S2 c3 L) `
1、构造一个CComBSTR对象; l* B3 N/ F9 s0 A @. }2 D
, ]6 o$ T8 Y+ G% [$ O2 P1 y$ ^
- CComBSTR bstr1;0 ~* F. b) A' m5 W* ^
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象4 @: r4 G1 p& ]" Q' O
9 {/ J5 S _4 Z- CComBSTR bstr2(L"this is a BSTR string");" r/ i' N9 j4 R
- MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象8 a, B3 y9 z6 Y8 f! t
- & _, G( I( o. `+ |
- CComBSTR bstr3(5);. p1 ]# _8 Z" V1 Z% Z9 A. S8 l
- MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。! y' ?) Y+ W+ R- U
6 O! X1 ~: b0 r% n0 k- CComBSTR bstr4(3,L"this is a BSTR string");
: b" G3 s) M6 P# T2 ?0 | - MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码 我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:
1 {" Q) ?7 M4 ]- m$ i5 U0 O- CComBSTR bstr1(L"this is a BSTR string");2 u4 y0 o- W% V: w7 e# y# P
- CComBSTR bstr2(bstr1);
# H3 E/ L4 q2 _/ \ - MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码 最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
& _) P5 \4 k6 Z9 Q) B7 Q4 H- static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};0 P3 \$ g+ f8 n% v) P
- CComBSTR bstr1(GUID_Sample);) v) B: s+ w! p/ m6 o( H0 {
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码 2、CComBSTR定义的常用操作如下1 T; F, U" e+ i# h, j6 e
(1)“=”操作符(赋值操作),如:( j' _; t2 B1 X* S/ o9 p8 ?
- CComBSTR bstr1(L"this is a BSTR string");+ x6 `4 t' w" K5 y
- CComBSTR bstr2=bstr1;
) l6 L6 y/ ]" \" J - MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码 (2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:5 i0 I" ^. P( j0 e- H. l2 j
- CComBSTR bstr1(L"this is a BSTR string");9 |1 ^: L* |8 s1 x
- BSTR bstr2=bstr1;
* E8 C P+ N4 D/ ~ - MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换7 N) y3 B# K3 H0 ^
2 f& H9 n8 d, J; S- CComBSTR bstr1(L"this is a BSTR string");
4 _* w, v: A; U* ]; N: e1 A. ^ - MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码 (3)!= 操作符,用来直接比较两个CComBSTR对象,如:; b3 D7 B! G1 ]) p! m; M$ o+ j) c
- CComBSTR bstr1(L"this is a BSTR string1");
1 ]0 K1 ^ k o; m# B! j4 t - CComBSTR bstr2(L"this is a BSTR string2");
9 C! _1 r4 |: _: } - if (bstr1!=bstr2){
3 m9 X5 Q' `; G7 w - MessageBox(NULL,L"true",L"BSTR test",MB_OK);
! G& G+ \8 w @! `' ]4 G - }& ^6 f8 N( L3 A/ V y) ]/ x \
- else( T. O) k, \1 X3 F- \
- {
+ p7 A( F" E" t8 a. V* S9 A, [/ y) P - MessageBox(NULL,L"false",L"BSTR 6 F& u L# f- @; J3 d* H, Z* J/ O/ ~
- test",MB_OK);
q; }( \" a- T1 m* B - }
复制代码 3、CComBSTR定义的常用方法如下
5 @- g: k3 U% {% V3 K6 M(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:
/ n; B+ N) J; {1 Q3 m- CComBSTR bstr1(L"this is a BSTR string1");9 b6 Z* `, a) K! a8 C. N$ O
- BSTR bstr2=bstr1.Copy ();6 l) S; O% ] s
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如: ! c; e0 |* G$ V: {/ f8 G, c
- CComBSTR bstr1(L"this is a BSTR string1");
8 S7 q( y8 u& P - BSTR bstr2;
# r V' L5 j' p$ n$ k3 O - bstr1.CopyTo(&bstr2);
( j0 |* A( J5 c% a/ G7 B" p8 b - MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
- V- w+ h7 y) K$ E$ s- BSTR bstr1=::SysAllocString (L"this is a BSTR string");
' F w; B( F; S- d) e - CComBSTR bstr2;
1 o4 V! Z* @$ K3 {( l$ R4 k$ D" h* { - bstr2.Attach(bstr1);$ @' ~/ K9 w: y, Z+ }$ v
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码 (4)Detach方法分离BSTR字串与CComBSTR对象,用法:! f. Z& a" M8 W
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。; |* m: ^" } h
/ `1 J( i# j/ v: S5 k$ y( f. O
|
|