将LPTSTR直接投射到BSTR是否合法?
根据我对BSTR的理解 ,将LPTSTR直接投射到BSTR将会给你带来一个损坏的长度前缀。 示例代码明确指出,string文字不能存储到BSTR。 任何人都可以确认一个LPTSTR / LPCTSTR不能直接转换到BSTR而不会破坏长度前缀?
编辑:
我的困惑是看到这个用于COM对象的调用。 事实certificate,编译COM DLL时,生成一个.tli文件,创build一个中间方法。 此方法采用_bstr_t
types。 _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
)。