你能把LPTSTR投给BSTR吗?

将LPTSTR直接投射到BSTR是否合法?

根据我对BSTR的理解 ,将LPTSTR直接投射到BSTR将会给你带来一个损坏的长度前缀。 示例代码明确指出,string文字不能存储到BSTR。 任何人都可以确认一个LPTSTR / LPCTSTR不能直接转换到BSTR而不会破坏长度前缀?

编辑:

我的困惑是看到这个用于COM对象的调用。 事实certificate,编译COM DLL时,生成一个.tli文件,创build一个中间方法。 此方法采用_bstr_ttypes。 _bstr_t可以在其构造函数中使用LPTSTR ,所以一切正常。

如果您的程序是unicode,并且您的LPTSTR因此是LPWSTR ,则可以使用SysAllocString将指针转换为宽字符字符串到BSTR

直接转换是不可能的,因为两者有不同的内存表示。

如果使用C ++,则可以使用_bstr_t类来简化BSTR字符串的使用。

如果您试图将LPCTSTR作为BSTR s传递,您会发现您将随机炸毁您所接近的任何互操作码。 编组将拉出一个LPCTSTR的4字节前缀(这是随机数据),然后尝试Marshall字符串。

你会发现4字节的前缀是缓冲区之前的堆栈内容,或者是来自前面字符串的更好的字符数据。 您将然后尝试maershall兆字节的数据… 🙂

使用CComBSTR包装并使用.Detach()如果您需要保持BSTR指针。

如果编译器吐出一个警告,那就好了。

一个LPTSTR是一个指向char数组的指针(或TCHAR)BSTR是一个结构体(或复合数据),包含*长度前缀*数据字符串*终止符

所以铸造将无法正常工作

不能这样做,因为LPTSTR之前的内存中的四个字节将被视为结果BSTR的长度。 这可能会导致内存保护错误(不太可能),但肯定会导致长度可能比原始LPTSTR的长度大的BSTR 。 所以当有人试图读取或写入,他们可能会访问无效的内存。

不,你不能 – 如果相信它的代码是一个BSTR调用SysStringLen()它将会运行到未定义的行为,因为该函数依赖于一些特定于实现的服务数据。

你不能投,你必须转换。 您可以使用内置的编译器内部_bstr_t (来自comutil.h )来帮助您轻松完成此操作。 样品:

 #include <Windows.h> #include <comutil.h> #pragma comment( lib, "comsuppwd.lib") int main() { LPTSTR p = "Hello, String"; _bstr_t bt = p; BSTR bstr = bt; bstr; } 

不,你不能直接施放它们。 但是,你可以做一个字符串,这两个。 C字符串没有4个字节的标题。 但是,中间的位是相同的,所以如果你发现自己需要这两个表示,那么可以创建一个包装类,它构造一个带有4字节头和一个空终止符的字符串,但可以将访问者返回到BSTR部分和C字符串。

此代码旨在作为一个不完整的例子,我没有编译这个!

 class YetAnotherStringType //just what the world needs { public: YetAnotherStringType(const char *str) { size_t slen = strlen(str); allocate(slen); set_size_dword(slen); copy_cstr(str, slen); } const char *get_cstr() const { return &m_data[4]; } const BSTR get_bstr() const { return (BSTR*)m_data; } void copy_cstr(const char *cstr, int size = -1) { if (size == -1) size = strlen(cstr); memcpy(&m_data[4], cstr, size + 1); //also copies first null terminator m_data[5 + size] = 0; //add the second null terminator } void set_size_dword(size_t size) { *((unsigned int*)m_data) = size; } void allocate(size_t size) { m_data = new char[size + 6]; //enough for double terminator } char *m_data; }; 

一般来说不是,但是有一些方法可以通过帮助程序类和宏在一定程度上兼容(见下文)。

1:1映射永远不可能的主要原因是一个BSTR (因此CComBSTR可以在字符串中包含'\0' ,因为最终它是一个计数的字符串类型。


使用C ++时,最好的选择是使用ATL类CComBSTR代替BSTR 。 无论哪种情况,您都可以使用ATL / MFC转换宏CW2A和朋友。

另请注意,文档(MSDN)说:

推荐的转换为和从BSTR字符串的方式是使用CComBSTR类。 要转换为BSTR ,请将现有字符串传递给CComBSTR的构造函数。 要从BSTR转换,请使用COLE2 [ C ] DestinationType [ EX ],如COLE2T

…适用于你的用例。

请参阅John Dibling的答案( _bstr_t )。