你能把LPTSTR投射到BSTR吗?

时间:2011-03-10 14:59:34

标签: c++ windows com string-conversion

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

根据我的understanding of BSTR,将LPTSTR直接投射到BSTR将为您留下损坏的长度前缀。示例代码明确指出字符串文字不能存储到BSTR。任何人都可以向我确认LPTSTR / LPCTSTR不能在不破坏长度前缀的情况下直接转换为BSTR吗?

编辑:

我的困惑是看到在调用COM对象时使用它。事实证明,在编译COM dll时,会生成一个.tli文件,用于创建中间方法。此方法采用类型_bstr_t。 <{1}}可以在其构造函数中使用_bstr_t,因此一切顺利。

8 个答案:

答案 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)。