zoukankan      html  css  js  c++  java
  • BSTR简介和内部结构

    转载自:http://blog.csdn.net/pkrobbie/archive/2007/01/18/1486331.aspx
    1         Why need BSTR
    
    COM是一种跨编程语言的平台,需要提供语言无关的数据类型。多数编程语言有自己的字符串表示。
    C++ 字符串是以0结束的ASCII或Unicode字符数组 
    Visual Basic字符串是一个ASCII字符数组加上表示长度的前缀。 
    Java字符串是以0结束的Unicode字符数组。
    需要定义一种通用的字符串类型,可以很容易的匹配到不同编程语言。在C++中,就是BSTR。
    2         What is BSTR
    2.1      BSTR 简介
    "Basic STRing"的简称,微软在COM/OLE中定义的标准字符串数据类型。对于C++,Windows头文件wtypes.h中定义如下:
    typedef wchar_t WCHAR;
    typedef WCHAR OLECHAR;
    typedef OLECHAR __RPC_FAR *BSTR;;
    2.2      BSTR实现
    在COM中,字符用16-bit OLECHAR表示,这样使COM可以支持各种code pages,包括Unicode。对于windows系统,可以简单理解为OLECHAR使用的就是Unicode 。OLECHAR串与单字节字符串很类似,是一个以null结尾的buffer。唯一的区别是每个字符占两个字节,而不是一个
     
     0 1 2 3 4 5 6 7 8 9 0 1
    | H | E | L | L | O | \0| 
     ^
     OLCHAR
     
     
    Figure 1. Format of an OLECHAR string. 
     
    使用以Null结尾的简单字符串在COM component间传递不太方便。因此,标准BSTR是一个有长度前缀和null结束符的OLECHAR数组。BSTR的前4字节是一个表示字符串长度的前缀。BSTR长度域的值是字符串的字节数,并且不包括0结束符。由于是Unicode串,所以字符数是字节数的一半。这种方式的优点是允许程序员在BSTR串中间嵌入NULL字符。但是,BSTR的前四个字节表示长度,而OLECHAR数组的前四字节表示前两个字符。这种情况下,对于C++程序,如何实现BSTR和OLECHAR的交换?答案是COM提供了两个BSTR分配用的API:SysAllocString / SysReallocString。函数返回的指针指向BSTR的第一个字符,而不是BSTR在内存的第一个字节。
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
    0a000000 | H | E | L | L | O | \0| 
                    ^
                  BSTR
     
    Figure 2.  Format of a BSTR. 
     
    下面是SysAllocString和SysFreeString的伪代码。
    
    BSTR SimpleSysAllocString( const OLECHAR * sz)
    {
        if ( sz == NULL) return NULL;
        
        BYTE* buf = new BYTE[sizeof(INT32) + (wcslen(sz)+1)*sizeof(OLECHAR) ];
        
        if(buf == NULL)
        {
            return NULL;
        }
        else
        {
            INT32 len = wcslen(sz) * sizeof(OLECHAR);
            *((INT32*) buf) = len;
            wcscpy( (WCHAR*)(buf+sizeof(INT32)), sz);
            return (BSTR)(buf+sizeof(INT32));
        }
    }
     
     
    VOID SimpleSysFreeString( BSTR bstr)
    {
        if(bstr != NULL)
        {
           BYTE* start = (BYTE*)bstr - sizeof(INT32);
           delete []start;
        }
    }
    
    3         When to use BSTR
    只有在你不得不用的时候。
     
    使用BSTR一般有以下几种情况:
    COM interface接口定义,并且不希望额外提供custom marshaling库(MDIL生成或开发人员自己订制),必须使用BSTR传递字符串。使用C/C++类型的字符串在COM DLL传递字符串,表面上可以使用,但违背了COM的基本规则,并且给以后的扩展留下了隐患。例如,把一个In-process COM Object(简单说COM DLL)改成out-of-process object(COM EXE)。理论上,客户端的代码应该不做任何改变。但如果是用了C/C++字符串,又希望只使用系统的automation mashaller(Oleaut32.dll),就会出错。
    如果可以提供custom marshaling,也推荐使用BSTR。 
    客户要求接口必须使用BSTR,和客户讨论后,不能修改。 
    使用的外部库的接口使用BSTR
     
    不使用的情况:
    不推荐在IDL结构体中定义BSTR成员,会给结构体的复制和释放带来麻烦。最好直接使用限定最大长度的TCHAR数组。如果确实需要传递变长字符串,BSTR应该被定义成独立的参数或者使用独立的get/set接口。 
    尽可能缩小的BSTR及相关类型的作用域范围。类的成员变量和函数参数不使用BSTR。局部变量要尽快释放类的内部不使用BSTR。代码处理逻辑中只在接口直接相关部分使用BSTR。接收到一个BSTR时,尽量立刻变成C/C++的字符串副本进行处理。在需要传递BSTR参数前产生BSTR,用过立即释放。
     
    字符串相关类型的推荐选择顺序
    优先级 类型 说明 
    最高 stl::string/wstring ·         功能最完善,可移植性最好。 
      CString ·         如果编码规范限制使用STL的时候,推荐CString。
    ·         VC 6的版本很不完善。.Net有明显改进,需要进一步研究。 
      C/C++ basic type(TCHAR* / char* / LPTSTR / LPCTSTR / TCHAR[]) ·         在结构体中,优先使用指定最大长度的字符数组。
    ·         效率最好 
      CComBSTR/ _bstr_t ·         在必须使用BSTR时的优先选择。
    ·         在ATL(COM component)工程或者工程中必须使用ATL中,优先选择CComBSTR。一般Exe/dll如果_bstr_t能满足要求,优先使用_bstr_t。
    ·         对于VC6,使用_bstr_t一定要慎重,最好只用作简单临时变量保存调被调用函数的传入参数。因为_bstrt_t不能支持一些关键性操作,比如Detach。
    ·         对于VC++ .Net推荐使用_bstr_t,它是C++扩展,不需要额外包含ATL的文件。 
    最低 BSTR ·         COM接口 
    
  • 相关阅读:
    MSSQL大量数据时,建立索引或添加字段后保存更改超时该这么办
    POJ 3261 Milk Patterns (后缀数组)
    POJ 1743 Musical Theme (后缀数组)
    HDU 1496 Equations (HASH)
    694. Distinct Substrings (后缀数组)
    POJ 1222 EXTENDED LIGHTS OUT (枚举 或者 高斯消元)
    POJ 1681· Painter's Problem (位压缩 或 高斯消元)
    POJ 1054 The Troublesome Frog (hash散列)
    HDU 1716 排列2
    HDU 4405 Aeroplane chess (概率DP & 期望)
  • 原文地址:https://www.cnblogs.com/macleo/p/1234742.html
Copyright © 2011-2022 走看看