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

BSTR 字符串

[复制链接]
发表于 2011-5-2 20:06:22 | 显示全部楼层 |阅读模式
原文:http://www.vckbase.com/document/viewdoc/?id=1911
% j* t# x4 f$ O  S) O( n
+ p+ o, u' f% d9 V; UBSTR是“Basic String”的简称,微软在COM/OLE中定义的标准字符串数据类型。 6 W6 C/ Y% d6 {8 ]" W
对于VC++,Windows头文件wtypes.h和WinNT.h中定义如下:
$ U0 Y0 k3 }" r6 g( F
  1. typedef /* [wire_marshal] */ OLECHAR *BSTR;9 \7 V8 s0 x+ T- B
  2. typedef WCHAR OLECHAR;$ c: f" Y5 f( @. k* L
  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 s5 ^, x  L# R
  2. INT  SysReAllocString(BSTR* pbstr,const OLECHAR* psz);
    ) ?5 k* k7 B: L3 c( W' e( Z- ]
  3. BSTR SysAllocStringLen(const OLECHAR * strIn, UINT ui);
    % `% h" K4 r( w+ f  c! T% q+ V
  4. INT  SysReAllocStringLen(BSTR* pbstr,const OLECHAR* psz,unsigned int len);
    # l( B4 O1 ^3 l4 {3 M
  5. void SysFreeString(BSTR bstrString);) W+ O6 j0 Z+ c, y( Z9 M
  6. UINT SysStringLen(BSTR);
    ! d  [0 L0 i' M, D; Y6 \
  7. UINT SysStringByteLen(BSTR bstr);
    5 u# T) ^( b& C9 h: U* P: D5 \
  8. BSTR SysAllocStringByteLen(LPCSTR psz,UINT len);
复制代码
下面对上述API用法进行说明。
2 s6 ^% @+ y$ \0 W2 Y) @7 O9 o# Y9 V
6 N9 f6 t' o* {0 ~3 x( F1、SysAllocString函数用于创建一个BSTR字符串,如:BSTR bstr=SysAllocString(L"create bstr string");就创建了一个BSTR字符串,上面说过BSTR字符串最初4个字节表示了字符串中字符个数,接下来是字符串中包含的真实字符,下面我们验证一下是否是这样的。我们生成一个WIN32控制台工程,生成时选择支持ATL的头文件,也可以后添加相应的头文件,主要是atlbase.h和atlstr.h,输入如下语句:$ h8 t% X# M/ x) z" P0 f
2 I. ]; |3 {6 g8 J" O$ q
printf("bstr front 4 byte is %x",*((int*)(((int*)bstr-1))));. _6 ^; \" Q  k8 z- K
. Y2 E" W+ ^/ e; x( P
语句中的bstr是以上刚刚生成的BSTR组符串,此语句显示的结果是“bstr front 4 byte is 24”换算成10进制正好是34,是“create bstr string”长度的2倍因为BSTR字符串中的字符是用Unicode表示的,而语句
/ O' U9 d# f, ^- b3 G6 x( N" c8 I5 N& n  w2 G/ l
printf("bstr front 0 byte is %c",*((int*)((int*)bstr)));6 |' f; S# N: h" D

' `! ?1 p, N+ A+ ?* ^输出的是“c”是语句中的第一个字符,语句
9 a) `8 M8 q( K4 K4 w: Q/ b  q/ S- i' }% y
printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));# }% q  t& i5 o+ z' b4 s" ?
6 l, e7 h& y% J+ X* ~
输出的是“g”语句中的最后一个字符,以上说明了SysAllocString函数用法及BSTR字符串在内存中的存储格式。
# n# `# V: _. C* R8 l. }% v* v( L/ D
2、SysReAllocString用于在一个已有的BSTR字符串的基础上重新建立一个BSTR字符串,输入如下的语句,可以检测该函数使用后的效果:
! |0 S3 |" P7 \/ I( \$ `- c, A
  1. BSTR bstr=SysAllocString(L"create bstr string");    " K+ H5 b5 E4 c4 F! r" q% V; t
  2. SysReAllocString (&bstr,L"new string");printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));; O- M+ `3 S) w: ?4 X. q
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));+ A' j# [+ ?' E: D# B& M
  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所指出的长度范围。但如果新的字符串如果超出原来串的长度,那么原来的字符串将被全部覆盖,长度以新的字符串为准,下面的语句说明了这一点。    t. r0 [6 Q) e6 }
  1. SysReAllocString (&bstr,L"new string new string");   
    6 F5 Y( l# }  i1 F( f! y
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    & F7 y/ y' Q5 r  @/ s
  3. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));2 @" d* Y8 L1 {  u) L' B8 `
  4. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
3、SysAllocStringLen按照指定的长度分配一个BSTR字符串,例如:3 P  |; ]6 y1 o
  1. BSTR bstr=SysAllocStringLen(L"create bstr string",6);   
    # L: x, \; Y) ^7 B8 F* j
  2. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));   
    0 h( x5 @& ~0 l: M
  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串。
+ _1 _7 z4 N# F& ^5 J: @8 q4、SysReAllocStringLen函数是在已有的字符串的基础上按指定长度重新分配一个新的BSTR字符串。如: . T; U3 Z7 w1 Z" q
  1. BSTR bstr=SysAllocString(L"create bstr string");   
    2 a  R, n2 P$ l  @
  2. SysReAllocStringLen(&bstr,L"new string",3);( [% U3 V* U+ _# M$ ?! }
  3. printf("bstr front 4 byte is %x\n",*((int*)(((int*)bstr-1))));9 F/ t/ b/ J4 W! h5 @' h# h
  4. printf("bstr front 0 byte is %c\n",*((int*)((int*)bstr)));
      i4 q% h4 ?6 ?* v/ f/ ~, H9 C
  5. printf("bstr front 35 byte is %c\n",*((char*)(((char*)bstr+34))));
复制代码
5、SysFreeString是释放一个BSTR字符串,BSTR字符串用后必须用此函数进行释放,例如: 6 `( L% @) D0 x7 o7 c& a7 M
  1. SysFreeString(bstr);
复制代码
6、SysStringLen求一个BSTR字符串的长度,如:
9 o. c- Y! A: s3 r
  1. printf("bstr size is %d\n",SysStringLen(bstr));其长度是指字符串中字符个数,而非字节数。
复制代码
7、SysStringByteLen求一个BSTR字符串的字节长度,如:$ o& J" g0 N8 V  {6 S
  1. printf("bstr size is %d\n",SysStringByteLen(bstr));
复制代码
8、SysAllocStringByteLen是按字节长度分配一个BSTR字符串。
, f( p: |( y4 {& Z- v* _3 b% d以上大致就是BSTR API 的用法,为了方便操作BSTR字符串,在ATL中建立了CComBSTR类专门用于操作BSTR字符,下面大致说说该类的用法。
/ _2 n9 _$ @- a, C) \& LCComBSTR类维护了公有的BSTR类型成员变量m_str,定义了8个构造函数用于创建CComBSTR对象,在析构函数中释放了m_str,在类中定义了常用的操作符并提供了对象持久性支持。
! t" B$ s) n0 }1 @" ]# f1、构造一个CComBSTR对象
1 c3 D% d7 @) ~, ]2 L, h" }8 v1 @% U) u- A! l. C- B
  1. CComBSTR bstr1;8 M3 F) `/ K& @  D* ?) |! S: [; n
  2. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK); 创建一个空的CComBSTR 对象2 z8 U7 D# ?# q1 U  B6 j

  3. - J% O% Z0 ^# x
  4. CComBSTR bstr2(L"this is a BSTR string");
    3 Y8 h, a- |  n) F! m$ n8 V5 D
  5. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK); 创建一个包含"this is a BSTR string"字符串的CComBSTR 对象! X9 N1 f- h* p) C$ u4 E
  6. 0 i/ g1 d' E3 _% {' _
  7. CComBSTR bstr3(5);4 m7 a9 l! ^/ @1 |! h$ d4 T
  8. MessageBox(NULL,bstr3.m_str ,L"bstr test",MB_OK);创建一个初始长度为5,含NULL的CComBSTR对象。
    . H4 u$ ^5 K& }( r# P4 P$ w
  9. 9 o2 }, }: k, P* a" y
  10. CComBSTR bstr4(3,L"this is a BSTR string");. B/ p  m3 J% K1 n' z: q& \$ s3 J
  11. MessageBox(NULL,bstr4.m_str ,L"bstr test",MB_OK);创建一个长度为3的CComBSTR对象,后面的字符串舍去。
复制代码
我们也可以从一个已经存在的CComBSTR对象创建另一个CCOmBSTR对象,如:4 h6 y0 V8 M0 z( R9 [* i
  1. CComBSTR bstr1(L"this is a BSTR string");
    0 H, \: B' e/ [! M+ N
  2. CComBSTR bstr2(bstr1);% O. Y% w9 u1 I8 F/ n9 I3 q, p! ~8 G
  3. MessageBox(NULL,bstr2.m_str ,L"bstr test",MB_OK);
复制代码
最后的一个构造函数比较奇怪,他接受一个GUID参数,生成一个包含GUID字符串的CComBSTR对象,如: 1 r: P7 C) T- @0 Z3 x$ i6 k
  1. static const GUID GUID_Sample={0X8a44e110,0xf134,0x11d1,{0x96,0xb1,0xba,0xdb,0xba,0xdb,0xad,0xcc}};' x7 S2 v, E6 G: f0 R
  2. CComBSTR bstr1(GUID_Sample);
    3 }  a% ]/ Z; y; p& S) ]
  3. MessageBox(NULL,bstr1.m_str ,L"bstr test",MB_OK);
复制代码
2、CComBSTR定义的常用操作如下- e8 W  r! \- A% m& w) a1 ?8 C
(1)“=”操作符(赋值操作),如:2 T4 t$ ]: @) b( B
  1. CComBSTR bstr1(L"this is a BSTR string");
    ! o' |$ r: Z3 F2 R+ Q" S0 f
  2. CComBSTR bstr2=bstr1;
    % X3 M" K& _8 {4 e# c
  3. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);bstr2和bstr1包含相同内容。
复制代码
(2)BSTR操作符把CComBSTR对象显式的或隐式的转换成BSTR字符串,如:8 q# i+ e) @/ `
  1. CComBSTR bstr1(L"this is a BSTR string");
      a. i/ {" \/ W. h' S8 o
  2. BSTR bstr2=bstr1;
    4 \, m; S$ S" T
  3. MessageBox(NULL,bstr2 ,L"BSTR test",MB_OK);隐式转换
    # Q- E' T; \6 m! s7 j

  4. ( j; B( l$ {: U3 ^6 c% H3 d& z( A
  5. CComBSTR bstr1(L"this is a BSTR string");
    - V! Y8 b& k/ q$ X# {: d
  6. MessageBox(NULL,(BSTR)bstr1 ,L"BSTR test",MB_OK);显式转换
复制代码
(3)!= 操作符,用来直接比较两个CComBSTR对象,如:' U9 Q( {) D' W- D1 @& q
  1. CComBSTR bstr1(L"this is a BSTR string1");0 R' |+ z% k  `6 R& c
  2. CComBSTR bstr2(L"this is a BSTR string2");* `+ l. n( G5 }! ?/ A
  3. if (bstr1!=bstr2){  E; z5 I+ s* L9 `/ T4 F& V
  4.         MessageBox(NULL,L"true",L"BSTR test",MB_OK);  q: w, l( O! A; R& n4 C
  5. }  ?9 v2 H0 }) F; k9 W- q2 z
  6. else! l, m& ~0 h# k$ ^( O" j
  7. {
    1 m7 L+ O, N/ t0 W0 |' ^3 Q
  8.         MessageBox(NULL,L"false",L"BSTR
    8 F, n: a0 Y; P! x; N0 i2 M
  9. test",MB_OK);* N( t% n; L8 W/ V# b: u
  10. }
复制代码
3、CComBSTR定义的常用方法如下
) _* K' U2 n+ p0 m(1)Copy 方法,该方法拷贝CComBSTR对象中的BSTR字符串并返回BSTR字符串,如:
& i' a0 c$ a! ^+ ^7 Q
  1. CComBSTR bstr1(L"this is a BSTR string1");- R- r7 m" k( a7 k1 X
  2. BSTR bstr2=bstr1.Copy ();; c% l9 k* D& A( |" L2 w9 Q7 t: r
  3. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(2)CopyTo 方法将CComBSTR对象中的BSTR字符串拷贝到新的位置,必须显式的调用SysStringFree来释放返回的字符串,如:
, C5 J; z8 j& x* I
  1. CComBSTR bstr1(L"this is a BSTR string1");
    ' {- P9 Q  m( J: p+ s0 d$ ^8 ^
  2. BSTR bstr2;+ [0 }/ j2 g9 d- {6 t- e- a
  3. bstr1.CopyTo(&bstr2);
    - x8 C: U5 P* f% r% @: b& h
  4. MessageBox(NULL,bstr2,L"BSTR test",MB_OK);
复制代码
(3)Attach方法把一个BSTR字符串附加到CComBSTR对象上,如:2 ?$ G+ A8 b! x
  1. BSTR bstr1=::SysAllocString (L"this is a BSTR string");# V0 v7 U8 r9 h/ `+ [% J
  2. CComBSTR bstr2;. k/ F  A8 z: I2 t5 x
  3. bstr2.Attach(bstr1);: M/ i) [' {1 H: x* R# P% q$ [
  4. MessageBox(NULL,bstr2.m_str ,L"BSTR test",MB_OK);
复制代码
(4)Detach方法分离BSTR字串与CComBSTR对象,用法:, Q3 p. d) N: H0 Q- o( ]: n
  1. bstr2.Detach ();
复制代码
(5)Empty 方法,释放对象中的BSTR字符串。 CComBSTR对象还有一些其它的方法,如附加字符串、大小写转换、对象持久性等并不常用。总之BSTR字符串是COM技术的基石,CComBSTR是处理BSTR字符串的利器,深入理解BSTR字符串是研究COM技术必须经过的关口。- U$ K! V1 q# P' A/ v& N
1 L* M% n* O; X0 z
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-5-2 10:21 , Processed in 0.025536 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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