- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
BSTR 是一个指向 UNICODE 字符串的指针,且 BSTR 向前的4个字节中,使用DWORD保存着这个字符串的字节长度( 没有含字符串的结束符)。因此系统就能够正确处理并传送这个字符串到“地球另一 边”了。特别需要注意的是,由于BSTR的指针就是指向 UNICODE 串,因此 BSTR 和 LPOLESTR (LPCOLESTR类型,是一个OLECHAR字符数组的常量指针。即该指针所指向的内容不能被修改)可以在一定程度上混用,但一定要注意:
有函数 fun(LPCOLESTR lp),则你调用 BSTR p=...; fun(p); 正确
有函数 fun(const BSTR bstr),则你调用 LPCOLESTR p=...; fun(p); 错误!!!(会提示:cannot convert parameter 1 from 'const unsigned short *' to 'unsigned short *const)。const BSTR bstr说明bstr是一个常量指针其指向不能改变,LPCOLESTR是一个指向常量的指针其指向的内容是常量。
有关 BSTR 的处理函数:
众所周知BSTR具有如下属性:
1. BSTR是指向一个带有长度前缀的OLECHAR字符数组的指针。
2. BSTR是指针数据类型,它指向字符数组的第一个字符。其长度是以整数存储在数组中第一个字符前面的位置(4个字节)。
3. 字符数组以NUL字符结束。
4. 前缀长度是指的字节长度,不包含结束符NUL。
5. 字符数组内部可能包含有效的NUL字符。
但是我们直接使用BSTR比较麻烦,需要自己手动分配释放内存,由如下两个函数完成:
str = ::SysAllocString() ,::SysFreeString(str),例如:
#include <iostream>
#include <atlbase.h>
using namespace std;
int main()
{
BSTR p = ::SysAllocString(L"Hello,你好");
return 0;
}
断点执行,然后观察p的内存)
含义如下:
为此我们可以考虑使用ATL提供的智能指针CComBSTR,在include\atlbase.h中可以找到其定义,如下:
// CComBSTR
我仅分析部分代码
class CComBSTR
{
public:
BSTR m_str;//被包装的BSTR成员
CComBSTR()//默认构造函数
{
m_str = NULL;
}
// explicit防止但参数构造函数的类型转换功能
//分配nSize+4字节的空间(未初始化)并把字符串首地址赋给m_str
/*explicit*/ CComBSTR(int nSize)
{
m_str = ::SysAllocStringLen(NULL, nSize);
}
//分配nSize+4字节的空间(初始化为sz)并把字符串首地址赋给m_str
/*explicit*/ CComBSTR(int nSize, LPCOLESTR sz)
{
m_str = ::SysAllocStringLen(sz, nSize);
}
/*explicit*/ CComBSTR(LPCOLESTR pSrc)
{
m_str = ::SysAllocString(pSrc);
}
//拷贝构造函数
//调用Copy()成员函数完成,典型的把公共操作封装为一个函数
/*explicit*/ CComBSTR(const CComBSTR& src)
{
m_str = src.Copy();
}
//将GUID转换成CComBSTR,见code2
/*explicit*/ CComBSTR(REFGUID src)
{
LPOLESTR szGuid;
StringFromCLSID(src, &szGuid);//将GUID转换成可打印的字符串
m_str = ::SysAllocString(szGuid);
CoTaskMemFree(szGuid);//释放StringFromCLSID中分配的内存
}
//赋值运算符,注意返回的是一个引用,从而使得连续赋值成为可能
CComBSTR& operator=(const CComBSTR& src)
{
//如果=左右的值是一样就直接返回没有必要做其他步骤
if (m_str != src.m_str)
{
if (m_str)
::SysFreeString(m_str);
m_str = src.Copy();
}
return *this;
}
//下面的=运算符使得可以把一个LPCOLESTR赋值给CComBSTR
CComBSTR& operator=(LPCOLESTR pSrc)
{
::SysFreeString(m_str);
m_str = ::SysAllocString(pSrc);
return *this;
}
//析构函数
~CComBSTR()
{
::SysFreeString(m_str);
}
//求长度
unsigned int Length() const
{
return (m_str == NULL)? 0 : SysStringLen(m_str);
}
//类型转换符,把一个CComBSTR强制转换成BSTR成为可能
operator BSTR() const
{
return m_str;
}
//重载的取地址运算符
BSTR* operator&()
{
return &m_str;
}
//辅助函数,一个公共操作函数
BSTR Copy() const
{
return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
}
//把智能指针CComBSTR所包裹的BSTR字符串拷贝到*pbstr中
HRESULT CopyTo(BSTR* pbstr)
{
ATLASSERT(pbstr != NULL);
if (pbstr == NULL)
return E_POINTER;
*pbstr = ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
if (*pbstr == NULL)
return E_OUTOFMEMORY;
return S_OK;
}
//让指针指针指向一个新的BSTR
void Attach(BSTR src)
{
ATLASSERT(m_str == NULL);
m_str = src;
}
//把智能指针CComBSTR所包裹的BSTR指针取出来返回并把智能指针置空
BSTR Detach()
{
BSTR s = m_str;
m_str = NULL;
return s;
}
//置空
void Empty()
{
::SysFreeString(m_str);
m_str = NULL;
}
//重载的!运算符判断CComBSTR是否为空
bool operator!() const
{
return (m_str == NULL);
}
HRESULT Append(const CComBSTR& bstrSrc)
{
return Append(bstrSrc.m_str, SysStringLen(bstrSrc.m_str));
}
HRESULT Append(LPCOLESTR lpsz)
{
return Append(lpsz, ocslen(lpsz));
}
// a BSTR is just a LPCOLESTR so we need a special version to signify
// that we are appending a BSTR
HRESULT AppendBSTR(BSTR p)
{
return Append(p, SysStringLen(p));
}
HRESULT Append(LPCOLESTR lpsz, int nLen)
{
int n1 = Length();
BSTR b;
b = ::SysAllocStringLen(NULL, n1+nLen);
if (b == NULL)
return E_OUTOFMEMORY;
memcpy(b, m_str, n1*sizeof(OLECHAR));
memcpy(b+n1, lpsz, nLen*sizeof(OLECHAR));
b[n1+nLen] = NULL;
SysFreeString(m_str);
m_str = b;
return S_OK;
} |
|