将LPTSTR直接转换为BSTR是否合法?
根据我的understanding of BSTR,将LPTSTR直接投射到BSTR将为您留下损坏的长度前缀。示例代码明确指出字符串文字不能存储到BSTR。任何人都可以向我确认LPTSTR / LPCTSTR不能在不破坏长度前缀的情况下直接转换为BSTR吗?
编辑:
我的困惑是看到在调用COM对象时使用它。事实证明,在编译COM dll时,会生成一个.tli文件,用于创建中间方法。此方法采用类型_bstr_t
。 <{1}}可以在其构造函数中使用_bstr_t
,因此一切顺利。
答案 0 :(得分:8)
如果您的程序是unicode且LPTSTR
因此是LPWSTR
,则可以使用SysAllocString将指针转换为宽字符串到BSTR
。< / p>
直接强制转换是不可能的,因为两者具有不同的内存表示形式。
如果您使用C ++,则可以使用_bstr_t类来简化BSTR
字符串的使用。
答案 1 :(得分:4)
如果您尝试将LPCTSTR
作为BSTR
传递,您会发现随机炸毁您接近的任何互操作编组码。编组将为LPCTSTR
提取4字节前缀(即随机数据)并尝试和Marshall字符串。
你会发现4字节前缀是缓冲区之前的堆栈内容,或者甚至是前面字符串中更好的字符数据。然后,您将尝试编组兆字节数据......: - )
如果您需要保留CComBSTR
指针,请使用.Detach()
包装并使用BSTR
。
如果编译器在这个问题上发出警告,那就太好了。
答案 2 :(得分:1)
不可能,因为LPTSTR
之前的内存中的四个字节将被视为结果BSTR
的长度。这可能会在现场导致内存保护错误(不太可能),但肯定会导致BSTR
的长度可能大于原始LPTSTR
的长度。因此,当有人试图从中读取或写入时,他们可能会访问无效的内存。
答案 3 :(得分:1)
LPTSTR是一个指向char数组的指针(或者确切地说是TCHAR) BSTR是由结构(或复合数据)组成的 *长度前缀 *数据字符串 *终结者
所以投射不起作用
答案 4 :(得分:0)
不,你不能直接施放它们。但是,您可以创建一个同时执行这两者的字符串。 C-String没有4字节的头。但是,中间的位是相同的,所以如果你发现自己需要两个表示,那么创建一个包装类,用于构造一个带有4byte头和一个空终止符的字符串,但是可以返回BSTR部分和C-String的访问器。 / p>
这段代码是一个不完整的例子,我没有编译过这个!
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;
};
答案 5 :(得分:0)
不,你不能 - 如果相信它的代码是BSTR调用SysStringLen(),它将遇到未定义的行为,因为该函数依赖于某些特定于实现的服务数据。
答案 6 :(得分:0)
你不能施放,你必须转换。您可以使用内置编译器内在_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;
}
答案 7 :(得分:0)
一般来说没有,但有一些方法可以通过辅助类和宏在某种程度上使它们兼容(见下文)。
永远不可能实现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
)。