|
|
原文:http://www.vckbase.com/document/viewdoc/?id=1911
. D4 W9 G5 a3 m4 L0 m
, u+ f: V2 ?% h: N" yBSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。
! e/ \; F2 o. n+ z# \+ g k! X对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下:
( x8 Z$ E6 ]) x% W G$ [% |- typedef /* [wire_marshal] */ OLECHAR *BSTR;+ Q) i4 t2 z* q* D% v) r
- typedef WCHAR OLECHAR;
, k. ?; \" o. O5 h - 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);
! \1 n4 }, v' r" V# o& t - INT SysReAllocString(BSTR* pbstr,const OLECHAR* psz);. b! v* G" L7 k" R- K5 ^
- BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);" J$ v5 [0 R+ U& M( e
- INT SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
. |3 W5 \9 C: l% v - void SysFreeString(BSTR bstrString);
$ t" o3 z& W) D - UINT SysStringLen(BSTR);
7 r# p, e! F h: X v: h - UINT SysStringByteLen(BSTR bstr);; r7 K: M! Z+ A' ~1 d
- BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码 下面对上述API用法进行说明。% X# C6 K" m. F4 `* I
- d0 R9 N" I: C) W/ C
1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:% {6 @1 L0 |; L3 u! z
: ~* } K' u4 X! U" Kprintf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));
: i# ?0 X( P6 V& l/ ]& }0 L* `% w) V- w
语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句1 Y2 g z/ G* L& M
: q" @" n/ _/ T" e/ R$ d; g
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));
* u1 T- w: n+ N/ O) o' Z! {* m6 @! l: y; W8 A s8 l! @
输出的是“c”是语句中的第一个字符,语句9 m; ~" n K) W( Q2 w: p
& A0 G ~3 B' l1 A& sprintf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));" O! @' H* R* q' K. i7 @0 w8 i. f5 i
U. |* \2 _- \
输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
% Q2 O9 M! M/ P# R+ i8 e! D1 Q9 y! C* V$ u3 o1 a3 r2 {/ f
2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:
* f& e! r- G# p, N- BSTR bstr=SysAllocString(L"create bstr string"); 3 d5 W' x+ r" d- |$ x' o0 V8 L1 q
- SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
, S0 ]' J/ r- s. k - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
4 a) D5 q) m% C) s% p3 E# J* h - 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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。 1 s# T$ S9 I; [# ?3 a- K5 @
- SysReAllocString (&bstr,L"new string new string");
( x9 O( K$ P0 N3 j6 ?8 ^ - printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
* A3 _0 f3 U- P% { - printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));2 s4 ?. O$ t3 u/ N7 h* n
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:1 S/ j, a7 Y" u1 b" r' }
- BSTR bstr=SysAllocStringLen(L"create bstr string",6);
5 ^9 _- }) c7 H7 E) m( K7 R+ c- w - printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
$ A# c$ T' p; R6 |/ c6 b" e - 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串。+ k# S6 v6 a5 u! s9 t6 d' p) F$ `* e
4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: . B+ q/ S1 s) G% p/ i
- BSTR bstr=SysAllocString(L"create bstr string");
% K1 j' a" @' c' q+ ` - SysReAllocStringLen(&bstr,L"new string",3);+ @, i" p2 v! h& Z/ w+ S1 q
- printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));- A! i( h' ?: @) S7 Y
- printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));: E% J! c, w9 b
- printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码 5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如:
- S; X5 [ T8 Q: B; ^6、SysStringLen求一个BSTR字符串的长度,如:* i8 Y. p3 O& H+ a- {$ M3 @% @
- printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码 7、SysStringByteLen求一个BSTR字符串的字节长度,如:1 x5 d( L9 o; t8 L2 P8 f
- printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码 8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。
2 `/ z* R J5 [* c0 X8 s以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。
- _8 ?; e9 K' m/ i% TCComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。6 D+ g/ A3 O: C9 M, Y" r% k: k3 O
1、构造一个CComBSTR对象
) r' D2 b4 p: b2 P3 j9 x* N4 J! u5 O. v; P$ Y, r- q: w
- CComBSTR bstr1;& W) o2 _8 S/ h% V
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象/ ` Q5 ^$ o5 {. P
- , ]! d# u- v! \" k2 H$ e2 M
- CComBSTR bstr2(L"this is a BSTR string");: H; n9 W9 X: i, D* [% {- v6 g
- MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象% A' ~+ i+ c4 N6 f, {. D
3 J4 v3 Z# \! ]4 `) C- CComBSTR bstr3(5);
% [5 ^8 V* Z# D5 e- \ ~ - MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。3 ?7 c) Y! z/ x& R9 C
- $ S" Y9 K2 a/ B$ H) K
- CComBSTR bstr4(3,L"this is a BSTR string");0 c6 C9 g: i Z! \* E
- MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码 我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:8 W* Y2 L8 W, t e8 D! x! }
- CComBSTR bstr1(L"this is a BSTR string");2 T& E( @. F4 p; s) Q
- CComBSTR bstr2(bstr1);% s/ E5 N9 H) i1 B- [: s
- MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码 最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
0 Y/ Y' i. i4 Y6 t+ E5 r- static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};
9 u) k9 l5 @9 C& R5 V - CComBSTR bstr1(GUID_Sample); e$ Q( x6 F+ c* w9 c' f
- MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码 2、CComBSTR定义的常用操作如下: W: [/ ?9 E" H: c; l- p9 b
(1)“=”操作符(赋值操作),如:) U* E ?3 ^3 Y+ T P
- CComBSTR bstr1(L"this is a BSTR string");
0 s$ M3 i' B+ ^! e/ R - CComBSTR bstr2=bstr1;3 D* p5 S* q3 i% Z
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码 (2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:8 M5 Z. _% u, C- t U$ Y4 X5 T9 Q
- CComBSTR bstr1(L"this is a BSTR string");
/ t5 O& g2 R G# y0 u1 t# Z+ i - BSTR bstr2=bstr1;0 A3 l7 W" m5 }1 B0 n2 S3 Z1 ?4 r/ g
- MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
( L( Q* a5 I9 C! Q - ; X' x7 ^, P0 X2 ?9 ~% `
- CComBSTR bstr1(L"this is a BSTR string");
$ X' t) c. f4 ^' W7 S - MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码 (3)!= 操作符,用来直接比较两个CComBSTR对象,如:
) M2 }' f% K& L$ N1 ~- CComBSTR bstr1(L"this is a BSTR string1");
5 v$ v9 k1 _% V- n: J, K+ \7 j - CComBSTR bstr2(L"this is a BSTR string2");
3 t y' R( ?$ W& q - if (bstr1!=bstr2){
/ T% l$ b! v2 n6 |' O - MessageBox(NULL,L"true",L"BSTR test",MB_OK);
) b0 D# y& x% u: @5 e4 n) N) D - }0 [# D# y: s6 F, G7 S3 a- ]0 I
- else2 P% |/ ^& Y9 Q2 u' \& p J2 W
- {6 [' S- _& W, h' I q
- MessageBox(NULL,L"false",L"BSTR
' U. L, D5 l! n: ~: ^- y - test",MB_OK);# P ]7 `% h. R
- }
复制代码 3、CComBSTR定义的常用方法如下
4 [0 @; _7 p5 o4 T" H(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:& \) G. M4 a# I9 A0 ^0 r
- CComBSTR bstr1(L"this is a BSTR string1");5 k! [+ {8 [0 D
- BSTR bstr2=bstr1.Copy ();* I8 t/ \0 O+ P; ~" u" @/ g. _, l
- MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如: 6 G1 `) S, [- W5 ]
- CComBSTR bstr1(L"this is a BSTR string1");1 X ]; J$ j5 l: Y
- BSTR bstr2;
0 }& {/ M8 ?/ I ?( _2 L, D% Z1 g7 U - bstr1.CopyTo(&bstr2);
8 j% q- I8 _4 M' W - MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码 (3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
6 F& d5 `% ^2 r/ V- BSTR bstr1=::SysAllocString (L"this is a BSTR string");$ {2 A1 F& s8 c' A
- CComBSTR bstr2;
5 J' C$ B- C H - bstr2.Attach(bstr1);4 p# i9 Q" o3 }4 o8 P1 d& Q
- MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码 (4)Detach方法分离BSTR字串与CComBSTR对象,用法:
+ ^ f7 H. j& K# a8 w' f5 [(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。- g' _. P$ z- p
1 W6 ]) U7 z, {% ?) S6 s" p
|
|