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

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文: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$ [% |
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;+ Q) i4 t2 z* q* D% v) r
  2. typedef WCHAR OLECHAR;
    , k. ?; \" o. O5 h
  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);
    ! \1 n4 }, v' r" V# o& t
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);. b! v* G" L7 k" R- K5 ^
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);" J$ v5 [0 R+ U& M( e
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
    . |3 W5 \9 C: l% v
  5. void SysFreeString(BSTR bstrString);
    $ t" o3 z& W) D
  6. UINT SysStringLen(BSTR);
    7 r# p, e! F  h: X  v: h
  7. UINT SysStringByteLen(BSTR bstr);; r7 K: M! Z+ A' ~1 d
  8. 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
  1. BSTR bstr=SysAllocString(L"create bstr string");    3 d5 W' x+ r" d- |$ x' o0 V8 L1 q
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));
    , S0 ]' J/ r- s. k
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
    4 a) D5 q) m% C) s% p3 E# J* h
  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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。  1 s# T$ S9 I; [# ?3 a- K5 @
  1. SysReAllocString (&bstr,L"new string new string");   
    ( x9 O( K$ P0 N3 j6 ?8 ^
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    * A3 _0 f3 U- P% {
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));2 s4 ?. O$ t3 u/ N7 h* n
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:1 S/ j, a7 Y" u1 b" r' }
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);   
    5 ^9 _- }) c7 H7 E) m( K7 R+ c- w
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    $ A# c$ T' p; R6 |/ c6 b" e
  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串。+ k# S6 v6 a5 u! s9 t6 d' p) F$ `* e
4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: . B+ q/ S1 s) G% p/ i
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    % K1 j' a" @' c' q+ `
  2. SysReAllocStringLen(&bstr,L"new string",3);+ @, i" p2 v! h& Z/ w+ S1 q
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));- A! i( h' ?: @) S7 Y
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));: E% J! c, w9 b
  5. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如:
- S; X5 [  T8 Q: B; ^
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:* i8 Y. p3 O& H+ a- {$ M3 @% @
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:1 x5 d( L9 o; t8 L2 P8 f
  1. 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
  1. CComBSTR bstr1;& W) o2 _8 S/ h% V
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象/ `  Q5 ^$ o5 {. P
  3. , ]! d# u- v! \" k2 H$ e2 M
  4. CComBSTR bstr2(L"this is a BSTR string");: H; n9 W9 X: i, D* [% {- v6 g
  5. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象% A' ~+ i+ c4 N6 f, {. D

  6. 3 J4 v3 Z# \! ]4 `) C
  7. CComBSTR bstr3(5);
    % [5 ^8 V* Z# D5 e- \  ~
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。3 ?7 c) Y! z/ x& R9 C
  9. $ S" Y9 K2 a/ B$ H) K
  10. CComBSTR bstr4(3,L"this is a BSTR string");0 c6 C9 g: i  Z! \* E
  11. MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码
我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:8 W* Y2 L8 W, t  e8 D! x! }
  1. CComBSTR bstr1(L"this is a BSTR string");2 T& E( @. F4 p; s) Q
  2. CComBSTR bstr2(bstr1);% s/ E5 N9 H) i1 B- [: s
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
0 Y/ Y' i. i4 Y6 t+ E5 r
  1. static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};
    9 u) k9 l5 @9 C& R5 V
  2. CComBSTR bstr1(GUID_Sample);  e$ Q( x6 F+ c* w9 c' f
  3. 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
  1. CComBSTR bstr1(L"this is a BSTR string");
    0 s$ M3 i' B+ ^! e/ R
  2. CComBSTR bstr2=bstr1;3 D* p5 S* q3 i% Z
  3. 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
  1. CComBSTR bstr1(L"this is a BSTR string");
    / t5 O& g2 R  G# y0 u1 t# Z+ i
  2. BSTR bstr2=bstr1;0 A3 l7 W" m5 }1 B0 n2 S3 Z1 ?4 r/ g
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
    ( L( Q* a5 I9 C! Q
  4. ; X' x7 ^, P0 X2 ?9 ~% `
  5. CComBSTR bstr1(L"this is a BSTR string");
    $ X' t) c. f4 ^' W7 S
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:
) M2 }' f% K& L$ N1 ~
  1. CComBSTR bstr1(L"this is a BSTR string1");
    5 v$ v9 k1 _% V- n: J, K+ \7 j
  2. CComBSTR bstr2(L"this is a BSTR string2");
    3 t  y' R( ?$ W& q
  3. if (bstr1!=bstr2){
    / T% l$ b! v2 n6 |' O
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);
    ) b0 D# y& x% u: @5 e4 n) N) D
  5. }0 [# D# y: s6 F, G7 S3 a- ]0 I
  6. else2 P% |/ ^& Y9 Q2 u' \& p  J2 W
  7. {6 [' S- _& W, h' I  q
  8.         MessageBox(NULL,L"false",L"BSTR
    ' U. L, D5 l! n: ~: ^- y
  9. test",MB_OK);# P  ]7 `% h. R
  10. }
复制代码
3、CComBSTR定义的常用方法如下
4 [0 @; _7 p5 o4 T" H(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:& \) G. M4 a# I9 A0 ^0 r
  1. CComBSTR bstr1(L"this is a BSTR string1");5 k! [+ {8 [0 D
  2. BSTR bstr2=bstr1.Copy ();* I8 t/ \0 O+ P; ~" u" @/ g. _, l
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如: 6 G1 `) S, [- W5 ]
  1. CComBSTR bstr1(L"this is a BSTR string1");1 X  ]; J$ j5 l: Y
  2. BSTR bstr2;
    0 }& {/ M8 ?/ I  ?( _2 L, D% Z1 g7 U
  3. bstr1.CopyTo(&bstr2);
    8 j% q- I8 _4 M' W
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
6 F& d5 `% ^2 r/ V
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");$ {2 A1 F& s8 c' A
  2. CComBSTR bstr2;
    5 J' C$ B- C  H
  3. bstr2.Attach(bstr1);4 p# i9 Q" o3 }4 o8 P1 d& Q
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:
+ ^  f7 H. j& K# a8 w' f5 [
  1. bstr2.Detach ();
复制代码
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。- g' _. P$ z- p
1 W6 ]) U7 z, {% ?) S6 s" p
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-18 06:16 , Processed in 0.017153 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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