找回密码
 注册
搜索
查看: 3932|回复: 0

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文: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
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;+ {2 T3 ?; ]( W2 Z
  2. typedef WCHAR OLECHAR;0 \  T4 S; f9 w) m' M1 F2 f
  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);$ z2 Q9 o# O# Z0 |8 _" P
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);7 _8 S5 h9 P' |  {/ c7 g! }& Y7 C& [! l
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
    ( M: l+ `* J+ j  i6 B- N# U
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);% q3 m+ m. E/ {8 m! M8 F+ u
  5. void SysFreeString(BSTR bstrString);! r3 P, D" ?- {
  6. UINT SysStringLen(BSTR);
    / T/ f/ }' {8 b; b6 f; K# o3 q5 L
  7. UINT SysStringByteLen(BSTR bstr);
    4 P6 F! G% E: n( l
  8. 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
  1. BSTR bstr=SysAllocString(L"create bstr string");    % c, u' t; x# D  [2 [9 W) `) N
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
    - D' p4 P( d$ v3 R
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));, |( P) ^: Y) [
  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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。  
  Z) g" J& ^" n$ y( E
  1. SysReAllocString (&bstr,L"new string new string");   
    % F. r$ e. V- j" Q7 L' |- _
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));    ) ^6 G# W! K) b% a
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
    2 i1 {5 w) t/ s! W0 l+ `" ]
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:
  n0 D" u. w% H7 N# K
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);    5 b$ y% |- I. S# y% t
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));      a8 \8 G; _" S* w; @2 s& X
  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串。5 a; \' W0 \3 o$ P& _7 w2 R
4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: * j. J* o1 k  v) s
  1. BSTR bstr=SysAllocString(L"create bstr string");    ( L8 K6 P% c* J% c
  2. SysReAllocStringLen(&bstr,L"new string",3);
    $ Q4 j- D- U3 m; X, O3 l
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));7 W- b6 F+ _% ^; B7 w* I7 m/ a
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));# C' s( V$ h$ y4 f- Q" T" w
  5. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: % g3 G( i, b3 T+ @" S* `
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:
( U9 v# }8 \" q& C. {* h  h
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:6 [" Z4 c* u& N5 t
  1. 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
  1. CComBSTR bstr1;
    2 T/ R0 x0 B$ q* g7 f" r
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象
    ; _/ B1 f, m: B" V

  3.   ~5 a0 J- N! t# c5 p& b* S3 A
  4. CComBSTR bstr2(L"this is a BSTR string");
    0 @4 P7 {! ~0 ^( g6 o
  5. 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# |
  6. + h: s2 y% ?; {3 O3 Z
  7. CComBSTR bstr3(5);
    # z, J: g" i4 @
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。2 d$ M' }# C2 S: G2 [3 j

  9. ! Q3 M# s6 P. j6 O, S. i
  10. CComBSTR bstr4(3,L"this is a BSTR string");+ s$ h6 f- k- g; a9 }1 n
  11. 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
  1. CComBSTR bstr1(L"this is a BSTR string");
    : I! z# c8 e2 z/ w
  2. CComBSTR bstr2(bstr1);
    0 \" w- Q9 H. E" j# F" A, h
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
; W* A" G8 I% p( d; ^( T9 e& q4 @/ z
  1. 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
  2. CComBSTR bstr1(GUID_Sample);
    ) w( I) _7 }. C9 c4 u7 ^
  3. 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
  1. CComBSTR bstr1(L"this is a BSTR string");4 k* R" L! m! `
  2. CComBSTR bstr2=bstr1;
    3 f( ^' K- e7 R% _( k1 f
  3. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码
(2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:
* X' X! g9 `: s% \- V/ f
  1. CComBSTR bstr1(L"this is a BSTR string");4 W1 r: U# s/ r4 {! K& w
  2. BSTR bstr2=bstr1;
    . U; N1 V- |& Z- @) O3 g0 m
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
    " k% o5 ]! v- z' M
  4. 3 B( Q0 w, [+ h1 p
  5. CComBSTR bstr1(L"this is a BSTR string");$ h$ Q$ Y  y/ n  m( a. Y8 l4 `
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:3 P! h7 z! O* V" j4 C
  1. CComBSTR bstr1(L"this is a BSTR string1");
    ! O  W, d' Z# R' n, H& C
  2. CComBSTR bstr2(L"this is a BSTR string2");
    . t6 x* t1 O' o
  3. if (bstr1!=bstr2){
    ' R" `$ R/ f% g7 K! e! n
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);8 z* X% d3 L: E* @3 W6 O0 Z, m! M
  5. }
    3 i$ [4 B7 v5 L4 s3 S5 h8 }
  6. else
    / G1 F( R  `" g3 M2 }0 t
  7. {/ ^9 ~! J3 h% u0 A
  8.         MessageBox(NULL,L"false",L"BSTR 4 x6 Q* F9 a# P5 [( h, A8 a% y
  9. test",MB_OK);
    - r$ U0 n2 @" t* A3 ]) g
  10. }
复制代码
3、CComBSTR定义的常用方法如下  f& a+ L# k/ x  m
(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:- T, D4 M- ]5 Z* X
  1. CComBSTR bstr1(L"this is a BSTR string1");' ]8 e) }1 f' \( s; ]5 i7 t
  2. BSTR bstr2=bstr1.Copy ();
    * @' z+ S# F8 u5 b
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如: 3 |* N: c7 _! L6 d) g
  1. CComBSTR bstr1(L"this is a BSTR string1");3 T) J3 L- D$ x) o) ~
  2. BSTR bstr2;' f9 w6 o8 M1 b# i. k, ^: P
  3. bstr1.CopyTo(&bstr2);+ B5 `# U5 R& E: B8 y  N. k
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
% U0 \6 }: d! I- d6 }0 s1 R, i
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");
    - x0 \( t, l4 Y& @4 Q3 b8 _
  2. CComBSTR bstr2;
    ) p: h7 o& o. c& r4 e: ?
  3. bstr2.Attach(bstr1);. Q3 j' Y. u9 F7 F9 i
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:8 T+ \( J8 h! r' M* Y! c
  1. bstr2.Detach ();
复制代码
(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
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 19:01 , Processed in 0.022390 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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