9

将 LPTSTR 直接转换为 BSTR 是否合法?

根据我对 BSTR的理解,将 LPTSTR 直接转换为 BSTR 会使您的长度前缀损坏。示例代码明确指出不能将字符串文字存储到 BSTR。谁能为我确认 LPTSTR/LPCTSTR 不能直接转换为 BSTR 而不会破坏长度前缀?

编辑:

我的困惑是因为在调用 COM 对象时看到了这个。事实证明,在编译 COM dll 时,会生成一个创建中间方法的 .tli 文件。此方法采用 type _bstr_t_bstr_t可以接受它的LPTSTR构造函数,所以一切都很顺利。

4

8 回答 8

9

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

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

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

于 2011-03-10T15:05:02.167 回答
4

如果您尝试将LPCTSTRs 传递为BSTRs,您会发现您将随机炸毁您接近的任何互操作编组代码。编组将提取 4 字节前缀(这是随机数据)LPCTSTR并尝试和编组字符串。

您会发现 4 字节前缀原来是缓冲区之前的堆栈内容,甚至是之前字符串中更好的字符数据。然后,您将尝试编组兆字节的数据... :-)

如果需要保留指针,请使用CComBSTR包装器并使用。.Detach()BSTR

如果编译器对此发出警告,那就太好了。

于 2011-05-12T03:06:36.240 回答
1

不可能,因为然后内存中的四个字节LPTSTR将被视为结果的长度BSTR。这可能会导致当场内存保护错误(不太可能),但肯定会导致 aBSTR的长度可能远大于原始LPTSTR. 因此,当有人尝试从中读取或写入时,他们可能会访问无效内存。

于 2011-03-10T15:02:57.950 回答
1

LPTSTR 是指向 char 数组的指针(准确地说是 TCHAR) BSTR 是结构体(或复合数据),由 * 长度前缀 * 数据字符串 * 终止符组成

所以铸造不起作用

于 2011-03-10T15:04:37.430 回答
1

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

于 2011-03-10T15:06:48.993 回答
0

不,你不能直接施放它们。但是,您可以制作一个两者兼而有之的字符串。C-String 没有 4 字节的标头。但是,中间的位是相同的,因此如果您发现自己需要两种表示形式,请创建一个包装类,该类构造一个带有 4 字节标题和空终止符的字符串,但可以返回 BSTR 部分和 C-String 的访问器。

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

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;
};
于 2011-03-10T15:03:53.383 回答
0

你不能施放,你必须转换。您可以使用内置的编译器内在函数_bstr_t(from 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;
}
于 2011-03-10T15:22:04.380 回答
0

一般来说没有,但有一些方法可以通过帮助类和宏在某种程度上使它们兼容(见下文)。

1:1 映射永远不可能的主要原因是 a 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)。

于 2011-03-10T15:54:50.270 回答