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

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文:http://www.vckbase.com/document/viewdoc/?id=1911
* o8 L7 A& X- ~7 s3 S1 P. n$ |$ A" G; w$ _; x
BSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。
3 k) \- p3 f5 X对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下: & Y( R. W( ^6 T
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;$ Q+ ~( g2 q- k! q' u
  2. typedef WCHAR OLECHAR;
    2 U2 N8 z# J1 E0 a# W) n- u
  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);
    , c& A+ @. t/ h# O/ Y$ _2 o
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);
    2 c6 ^& b1 F: v  p8 `$ q  R4 T
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);+ u1 ^2 P- w" }  j) g& x
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
    , k2 K% H- l) Z1 a
  5. void SysFreeString(BSTR bstrString);/ H: r8 c, G3 @# f0 F
  6. UINT SysStringLen(BSTR);
    * w' C, G+ \; ?. @! }' }) d% i
  7. UINT SysStringByteLen(BSTR bstr);9 `: b- z  d5 `& P3 w( W" q% j% }
  8. BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码
下面对上述API用法进行说明。5 S$ v6 m$ Q  K  _! H  y5 N( ]% D
% }3 {0 V* h3 A1 U
1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:
8 W" ^! d# D, d' L9 q; y( h9 x* s) w% r
printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));& v& p/ Y# w6 g7 y0 C' P2 J1 D' [5 J
: i, w$ c6 L9 n) g* r  Z7 [; k
语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句: R7 J: L+ c1 f( \
" c2 s5 P# e1 k! r% x$ j
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));. b' I2 X6 M" k, F9 N9 t

6 w1 C1 i7 S& @2 N6 O0 o输出的是“c”是语句中的第一个字符,语句
' _9 x# L8 W) `+ a8 j5 O; I% p, K
printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
1 y: _  ~/ f( B2 v* f6 ~/ _6 ~; ^# ^& T4 P  j: K
输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。1 d( K" y7 |! I4 ?8 K* Q1 a+ M# d

# O9 \* f  |: G- `9 t# l/ W2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:
, K8 G7 a& X# b2 Y6 M# p( @6 V: f9 Z& Y
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    , u* ]4 D- r) F; R* k0 h
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));5 j) ?+ Y! R9 ?; \
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));& d) Y. x. m3 }0 |( 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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。  
/ l. E7 P1 T! b* U- {' j8 [  }
  1. SysReAllocString (&bstr,L"new string new string");   
    6 C+ m1 d( @8 k" Y% I
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));    ! Q- f+ X3 Y, h) O8 p, c- c; u6 k  l
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
    9 t. S/ f# t, L, l9 A$ S5 P# T
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:1 F& c* }' D5 T
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);   
    0 m  G) V  z, c# A, G  d' K
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    ( ]. \# X. a2 _
  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串。
4 H( s/ f: Q( ]" z4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: 7 r! t( N* N5 C$ V
  1. BSTR bstr=SysAllocString(L"create bstr string");    & m# H8 D, f5 F3 e- Z
  2. SysReAllocStringLen(&bstr,L"new string",3);5 x$ J! p! n$ }& A. C) h
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));- u0 `0 p+ O2 Y7 l
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));! H+ b) L2 ]$ `2 M% k5 Y  P9 S
  5. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: ' H/ `  u* q3 y. U( k
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:
9 D  f* Q1 H' W: Y3 x9 X
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:/ s% x, U& F  \% d
  1. printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码
8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。
! w: ~. r/ c8 m以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。
; @* I( z) }! q3 }CComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。$ ~( u. a4 c8 G$ c0 u* K
1、构造一个CComBSTR对象
8 W! o- E, c6 j
) D& d& @/ ~- q8 i1 e9 n$ B
  1. CComBSTR bstr1;  L  L3 g; Q; b. f1 j) _3 L
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象9 \, K) q$ |0 c$ H) ^4 S/ d+ l+ _5 v( j

  3. / x# r8 g9 `6 }& }1 R$ [7 ^8 E
  4. CComBSTR bstr2(L"this is a BSTR string");( J$ }5 G1 d  ?% D
  5. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象
    9 f/ y' ~) O8 X* O* q. z

  6. - m0 ~" ?2 L$ _0 f: v5 N( W
  7. CComBSTR bstr3(5);
    9 H, H3 a& s. ^1 ]. s% L- r/ O
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。% t# f$ e% [( A; ^+ f

  9. - W4 E9 a# U, n$ g- A, B) D* r" z
  10. CComBSTR bstr4(3,L"this is a BSTR string");( z0 y  q% c2 i3 n# _4 S" y* s4 j: T
  11. MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码
我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:0 g3 O2 y: K6 L0 f. L0 W
  1. CComBSTR bstr1(L"this is a BSTR string");
    ; U# {+ J; E  ^- r5 d7 j5 z
  2. CComBSTR bstr2(bstr1);9 O# m. E- @& k/ U0 R5 L- U; \
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如:
2 O) b/ ?  Y8 u- P8 [7 J* O2 Q% W' J# c9 B
  1. static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};
    + L2 G. i3 e3 L! ]* G
  2. CComBSTR bstr1(GUID_Sample);* M8 k( v+ y' P3 |& m* z5 K5 t
  3. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码
2、CComBSTR定义的常用操作如下
' ~5 `' g: U# K- g$ x, m+ P(1)“=”操作符(赋值操作),如:0 M4 n% m9 a/ V  ^9 E
  1. CComBSTR bstr1(L"this is a BSTR string");
    % M+ y1 W* d% F- h- R: u+ b
  2. CComBSTR bstr2=bstr1;5 b1 ^3 S1 N; _6 B
  3. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码
(2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:! n5 p' `! W# U
  1. CComBSTR bstr1(L"this is a BSTR string");
    + X" Y6 Q) T3 U4 V" `  }8 h
  2. BSTR bstr2=bstr1;) z9 ^0 `+ d: s, W5 K# U' W
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
    ) k2 K% M7 B$ ^8 s

  4. $ p8 a& x! F/ A# x5 S5 B$ }
  5. CComBSTR bstr1(L"this is a BSTR string");
    * u# i3 B, [1 W" C  [6 o
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:
/ I# S) C5 Q  X+ N
  1. CComBSTR bstr1(L"this is a BSTR string1");8 P! ]4 H: N( `) M
  2. CComBSTR bstr2(L"this is a BSTR string2");
    & s: Z3 D4 B1 f1 k, f# y/ s
  3. if (bstr1!=bstr2){
    + C1 t, A" l- U- _; |0 D5 @& B, P
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);
    ) N) A0 n1 z8 _1 {4 M
  5. }
    $ T$ Q0 K  h5 Y
  6. else% b4 g: l2 Q7 p3 {# `- @
  7. {
    7 p9 q- L- P* r+ f7 D5 [! m
  8.         MessageBox(NULL,L"false",L"BSTR : y. z  ]8 ?) v# G! a1 @, ~
  9. test",MB_OK);, q3 o4 R5 n$ K2 E# R
  10. }
复制代码
3、CComBSTR定义的常用方法如下
/ b" F! C2 i- [  @3 |$ G( ~0 V(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:
# ?% a3 Z# Y6 T' [& K
  1. CComBSTR bstr1(L"this is a BSTR string1");
    5 ^. H  G0 V- E6 [3 t. _$ R5 Z2 B
  2. BSTR bstr2=bstr1.Copy ();( p1 X% d6 R  G
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
7 I1 t# m# Y6 Z) s, _3 X) B
  1. CComBSTR bstr1(L"this is a BSTR string1");3 L/ O8 `& p$ B7 ]% \
  2. BSTR bstr2;
    7 D' ^3 d5 ]4 q6 |
  3. bstr1.CopyTo(&bstr2);5 V; E5 P4 v/ }/ w! H5 @7 B
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:
7 D/ s7 D' R  S" g
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");$ [+ d1 g. H8 m, T3 |0 L5 r, u
  2. CComBSTR bstr2;
    & @  y4 \0 l' y
  3. bstr2.Attach(bstr1);) \* z" k- E' s; B6 S9 l! t! Z
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:
7 x8 N! I6 z) ~0 r8 {" `
  1. bstr2.Detach ();
复制代码
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。
1 o7 @) d4 n! d5 N8 c# {
8 Z/ A0 R$ Y- j  a9 V1 w
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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