找回密码
 注册
查看: 4029|回复: 0

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文: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
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;
    . A$ }) X' p4 a! }- T9 T
  2. typedef WCHAR OLECHAR;1 l% X7 W) ^. J" v
  3. 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,分别是:
  1. BSTR SysAllocString(const OLECHAR * psz);
    2 w( u* ~2 _$ G2 _
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);6 q5 [- ?, N" Z! [1 A. T. W6 T
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
    ; k& t, D4 U4 [% x! I  \
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
    ( {5 o; ^% ]6 V' e
  5. void SysFreeString(BSTR bstrString);
    ; {" M4 O4 e& Q2 H! }9 N
  6. UINT SysStringLen(BSTR);
    ( e! u6 ~6 E8 H! W) O9 _+ n
  7. UINT SysStringByteLen(BSTR bstr);
    3 e7 t2 Q6 m# C+ k, ?6 g
  8. 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) {
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    3 |! R% J# n( h1 B/ f' g# N2 |
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
    # b% l# Y" X( ]5 d+ w
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));2 Y: u' x' j. S! b( u8 ]
  4. 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
  1. SysReAllocString (&bstr,L"new string new string");    . f. p2 J0 j  h5 [" y
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    $ j; F/ S0 O" Y" C. u' A; l
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));) Y& `# D/ q' g6 Z, b2 S
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:2 S1 @$ d2 d* e$ U5 p* K& m
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);    9 {, G; l, F) C, P& C! n7 g
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));    8 }4 y* i1 |2 D
  3. 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
  1. BSTR bstr=SysAllocString(L"create bstr string");    - g0 N4 r, {& a) b% k
  2. SysReAllocStringLen(&bstr,L"new string",3);5 f0 S4 ?$ l: [. m3 P. v8 }* p" J: B2 i
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
    ( f% G) B$ h" k6 |) f; k, z
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
    . x$ }9 z( p/ e2 I1 W6 D
  5. 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
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:
0 R2 j9 ^9 x7 f
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:$ x& `" c  y: j3 q( j6 b6 M- o
  1. 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 }
  1. CComBSTR bstr1;
    $ r  M. L  W- h7 ?( i) ?
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象
    4 B2 |8 U/ b" l9 {$ ?' K8 k
  3. 8 G5 ]4 {! V9 }& k: _$ B
  4. CComBSTR bstr2(L"this is a BSTR string");
    - |  g7 {! X8 i+ i7 V* n  N8 H( L
  5. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象9 X5 y. N7 m+ b6 ]+ ?
  6. 8 p0 l1 Q5 H7 x  \+ g0 F
  7. CComBSTR bstr3(5);/ z. p( n% x+ r/ Z
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。
    " W3 b% Q% B5 C
  9. 2 J2 r" y  N& A6 u
  10. CComBSTR bstr4(3,L"this is a BSTR string");
    0 R1 y4 r3 ^7 X
  11. MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码
我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:$ m; t0 _& |2 _9 L/ U2 |3 X( s! E
  1. CComBSTR bstr1(L"this is a BSTR string");
    ' S0 w- a; A) W6 S" I' b+ v
  2. CComBSTR bstr2(bstr1);
    ! W1 e) t& m' D1 Z8 o
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
, o6 q5 ?$ n0 W
  1. 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
  2. CComBSTR bstr1(GUID_Sample);& j" e5 X* N# N9 K
  3. 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
  1. CComBSTR bstr1(L"this is a BSTR string");
    $ C1 V# Y3 L& |# o1 u
  2. CComBSTR bstr2=bstr1;7 E) T2 {# ^! ?/ J+ E
  3. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码
(2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:+ X/ @& ^/ f, o/ I# Q2 C
  1. CComBSTR bstr1(L"this is a BSTR string");# J4 O( b! W4 a( |+ {
  2. BSTR bstr2=bstr1;0 |0 w# Y! t( y9 L3 U0 M
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
    : B" g& q( b) H, }
  4. 1 c. ]9 V9 L- x
  5. CComBSTR bstr1(L"this is a BSTR string");
    $ U% M1 g) \  O/ [1 \
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:  v) t# Z: d$ @/ p" z
  1. CComBSTR bstr1(L"this is a BSTR string1");; E# W( Z6 z2 C" \) n, J
  2. CComBSTR bstr2(L"this is a BSTR string2");
    * {5 _1 W0 C( ^/ V) @- n
  3. if (bstr1!=bstr2){/ H' l5 c8 G; x! N% O: m+ ^' n5 c
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);
    3 M# ^$ J% F9 A/ e+ n7 z0 H
  5. }
    2 `0 V) Q  v! _8 m% }: ?
  6. else
    + Y+ b8 I, e6 N* c
  7. {; B" C7 Z# r, G, W2 w# o: j
  8.         MessageBox(NULL,L"false",L"BSTR
    , g/ `, |5 L& b, Z; G( {/ a- G
  9. test",MB_OK);: ^$ ~% ^, s3 {4 c5 |9 L
  10. }
复制代码
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: @
  1. CComBSTR bstr1(L"this is a BSTR string1");
    * k, P' L5 ^$ q
  2. BSTR bstr2=bstr1.Copy ();; m9 |2 z/ r3 u  s9 ?
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
. q) J  z, B  c
  1. CComBSTR bstr1(L"this is a BSTR string1");' k8 Q1 `+ e7 U: @0 N5 O7 \
  2. BSTR bstr2;
    + s: ]5 q9 z( _' C" {+ T$ a. Z
  3. bstr1.CopyTo(&bstr2);! l: U9 j7 E+ y4 j3 C# U& S# ?
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
% Z$ e; h- K) D; K# i* ]. b
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");* T7 o3 a0 M; x" L4 c
  2. CComBSTR bstr2;- x/ l6 O& p; Z7 j: [6 b
  3. bstr2.Attach(bstr1);
    ) [& O" J  V; G+ n3 t7 e
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:
" k- S$ J/ e1 J+ _/ n7 p: A- ^
  1. bstr2.Detach ();
复制代码
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。' ?+ F. A/ A& T  C

) N( W0 _% x% m8 r; b. ]  q8 y
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-10-1 23:52 , Processed in 0.016283 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表