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

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文:http://www.vckbase.com/document/viewdoc/?id=1911
; o. f9 P0 N! ?- H1 H1 o) k/ I" a5 H7 e
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。 ! x6 o& r0 P3 H$ }
对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下:
' H+ u$ k2 Y. e% |3 A7 S" Z7 f" B
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;
    ) |$ Q5 m# u2 f; \& C6 J: _
  2. typedef WCHAR OLECHAR;* ^* C5 r2 B4 }$ X  @/ A
  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);
    7 C% ^5 O3 d) Q! j
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);
    * y' t; |, X$ H5 k+ K
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
    1 z7 D. H1 X+ I7 l$ X4 f( S
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);- R0 w, Y8 |: a3 S4 Q/ p9 n
  5. void SysFreeString(BSTR bstrString);4 L& W% D3 [( }/ y8 P
  6. UINT SysStringLen(BSTR);
    6 z4 Z0 }4 `& ]3 }$ G5 q3 e
  7. UINT SysStringByteLen(BSTR bstr);5 @$ Y. ~+ n) o& J! E$ O% T, F
  8. BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码
下面对上述API用法进行说明。
% @& o" i6 j: I3 h+ A& D! o) C+ b8 _1 u' Q
1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:9 ^4 S+ x+ m+ D2 |2 ]
& @$ I. C- W% m7 q0 e' u' U, _( }
printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));
) |+ [8 L4 c( X- e7 \% _* J- X' a( l! \# S3 r3 z
语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句
1 o0 T. o+ _  q$ R
# }! V, Y6 D/ P, @$ ]* K8 c) Zprintf("bstr front 0 byte is %c",*((int*)((int*)bstr)));
! z" o) t$ q2 X6 m6 [( \8 v2 \: x: ?% d! |- n- v) ^
输出的是“c”是语句中的第一个字符,语句/ K6 i" m. t& }! v4 i( ?- H

" ?0 T  d/ \( K. Nprintf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
6 e  s- j' ]/ U1 q& p! \9 Q- T& |# F4 c2 ^8 Y
输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
$ o; g! W9 s  l% B
6 b# i$ j& m6 |2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:1 K# L3 k& j/ I9 y1 v
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    9 Z  f. H' I  n3 U. E
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
      ^& A) Y, b" \. s2 Y# U  w
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
    , e5 G" l0 H2 c. T+ a
  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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。  * x, a6 G7 i! k
  1. SysReAllocString (&bstr,L"new string new string");   
    / v1 t: Z1 |* l) [/ [/ j
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));    " j0 \. P. G5 _3 }3 b' R8 f
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));/ R! h) V, C3 l: p) o/ {( ~7 m5 e
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:5 `. K6 s. G" ^& T' L9 M1 @! K
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);    9 F! ?4 ?  s3 t/ p
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));    , o0 x# x  j' o9 q( n
  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串。* d' x' C; H9 c
4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如:
: E) V+ ^/ k) N4 Y5 J) {
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    9 F% I9 `+ k: O" G; M; q' ~! F* P
  2. SysReAllocStringLen(&bstr,L"new string",3);
    4 G- J7 k2 _- g5 d6 S
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));+ _* Y' I. u# A& ?' n( l- ?
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));+ _( f, n0 T+ ~
  5. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如:
/ M7 [2 S/ g4 |5 s: `% l
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:! Q- u- b9 J1 ]( W+ @0 F
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:9 G+ @3 S4 r, d9 H3 y) h+ y+ ?7 p( N
  1. printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码
8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。
& \8 W9 n) P' A) D1 M$ N以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。, A* d$ |8 A4 p9 ~
CComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。
9 _9 v* a0 U! h, X: D4 s" D1、构造一个CComBSTR对象: y: }. x1 L5 n9 @0 }

* r6 `+ l; G$ }! g
  1. CComBSTR bstr1;( N1 m- o& \; {* G  ^" w  t) }
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象9 E- U7 ^+ d* S

  3. ) w& X# ^7 w# X, o
  4. CComBSTR bstr2(L"this is a BSTR string");9 L8 n! a; v# z2 e; T5 w
  5. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象: L- a+ N% G) B" j9 q$ L

  6. $ J2 G$ u0 y/ S1 U* J
  7. CComBSTR bstr3(5);7 L- V/ k1 m2 H2 V% X( j0 g5 i: i1 G& v
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。
    ) ?( W' C" Y" [  f+ U. o3 y
  9. 0 J  y7 m& h) K, @4 P' g. O! r
  10. CComBSTR bstr4(3,L"this is a BSTR string");
    ; J8 c2 B5 s' s3 H4 O; T
  11. MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码
我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:
8 k' w. [* @7 B% S
  1. CComBSTR bstr1(L"this is a BSTR string");) ]# `$ k0 C- X& C, O
  2. CComBSTR bstr2(bstr1);
    . [5 j3 p2 r' K/ s8 M
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如: 5 h' F6 ^: _' [7 O
  1. static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};% f. `0 Y5 f# y: S3 P" ^
  2. CComBSTR bstr1(GUID_Sample);
    $ ~2 W. ^' \# b8 B6 r' _) g. y+ u
  3. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码
2、CComBSTR定义的常用操作如下2 ~( y9 b; w' ~0 J
(1)“=”操作符(赋值操作),如:" M) ]6 E/ F; D! V; ?, K0 e
  1. CComBSTR bstr1(L"this is a BSTR string");4 q$ F; W/ J0 |
  2. CComBSTR bstr2=bstr1;+ V2 e6 d" D6 z3 U! B5 T
  3. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码
(2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:* F9 ^8 _4 l. W% w, `
  1. CComBSTR bstr1(L"this is a BSTR string");5 ^3 {  _" Z- A9 L" s
  2. BSTR bstr2=bstr1;
    5 ^9 {9 m1 d# a$ w
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换$ T: U- t9 D4 K; k% I+ Y

  4. 6 B( w2 [( x7 r& N# T7 m5 f( z
  5. CComBSTR bstr1(L"this is a BSTR string");& j1 f; c) r" \$ |" l
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:
/ C% ?8 M* z& g; s' R" k2 q% b
  1. CComBSTR bstr1(L"this is a BSTR string1");
    / t$ n1 \+ l% \/ H  _
  2. CComBSTR bstr2(L"this is a BSTR string2");5 r: E: r5 `: F2 m6 x
  3. if (bstr1!=bstr2){: f; Z( ~- P7 V+ y# W& h2 c
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);; A2 q# X: l) {' j/ e
  5. }% x, P7 r! i$ a; j# L9 x9 \1 `
  6. else
    , \+ I; a; D# W7 @4 ?; Y
  7. {
    " d# c, ^$ L; v: S; e$ n0 w; k3 j
  8.         MessageBox(NULL,L"false",L"BSTR ( D3 D4 z. E/ g# }: |
  9. test",MB_OK);
    ) B. |5 l6 l, g3 n+ \
  10. }
复制代码
3、CComBSTR定义的常用方法如下
" }9 `9 M# t1 e: t(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:- r( @1 P9 P* c! u) }
  1. CComBSTR bstr1(L"this is a BSTR string1");
    2 j. F& _  z0 S& x" t& X
  2. BSTR bstr2=bstr1.Copy ();
    * ?0 @: }2 _% o3 n1 O% ~
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
% ^1 B# h7 R& A3 n
  1. CComBSTR bstr1(L"this is a BSTR string1");$ B8 ]+ v; A4 b% x( [( X- z% N
  2. BSTR bstr2;) O  e# y- x1 j" Q0 w  ?
  3. bstr1.CopyTo(&bstr2);2 K  b# }. A( ?# Z7 v/ R# b% ~# h+ Z8 Q6 _
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
( N0 H6 x5 e2 P1 P3 g! {9 b
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");6 ^5 x! P' A5 V! C! W' q
  2. CComBSTR bstr2;" v% c9 L* p1 A& J% [# E- X* P& N
  3. bstr2.Attach(bstr1);
    ! l( W- y# z) v0 s
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:1 h! J. w8 ~9 G7 ]4 Y, a6 G
  1. bstr2.Detach ();
复制代码
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。. v: ^6 R8 v0 W! O9 R  A

: H4 `/ r! L( L- p5 }$ u
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 10:13 , Processed in 0.017184 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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