windows 您可以将 LPTSTR 转换为 BSTR 吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5261515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:23:45  来源:igfitidea点击:

Can you cast a LPTSTR to a BSTR?

c++windowscomstring-conversion

提问by Mashmagar

Is it legal to cast a LPTSTR directly to a BSTR?

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

Based on my understanding of BSTR, casting a LPTSTR to a BSTR directly will leave you with a corrupted length prefix. The example code explicitly states that a string literal cannot be stored to a BSTR. Can anyone confirm for me that a LPTSTR/LPCTSTR cannot be cast directly to a BSTR without corrupting the length prefix?

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

EDIT:

编辑:

My confusion is from seeing this used in a call to a COM object. It turns out that when compiling the COM dll, a .tli file is generated that creates an intermediate method. This method takes type _bstr_t. The _bstr_tcan take LPTSTRin its constructor, so everything works smoothly.

我的困惑是看到在调用 COM 对象时使用了 this。事实证明,在编译 COM dll 时,会生成一个 .tli 文件,该文件会创建一个中间方法。此方法采用 type _bstr_t。该_bstr_t可以采取LPTSTR在其构造,所以一切工程进展顺利。

回答by Timbo

If your program is unicode and your LPTSTRtherefore is a LPWSTR, you can use SysAllocStringto convert from a pointer to a wide character string to BSTR.

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

A direct cast is not possible because the two have different memory representations.

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

If you use C++, you can use the _bstr_tclass to simplify the usage of BSTRstrings.

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

回答by Chris Turner

If you are trying to pass LPCTSTRs as BSTRs you will find that you will randomlyblow up any interop marshalling code you get near. The marshalling will pull the 4 byte prefix (which is random data) for an LPCTSTRand try and Marshall the string.

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

You will find that the 4 byte prefix turns out to be the stack contents prior to your buffer, or even better character data from the string before it. You will then try to marshall megabytes of data... :-)

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

use the CComBSTRwrappers and use .Detach()if you need to keep the BSTRpointer.

使用CComBSTR包装器并.Detach()在需要保留BSTR指针时使用。

Be nice if the compiler spat out a warning on this one.

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

回答by nobs

A LPTSTR is a pointer to a char array (or TCHAR to be exact) BSTR is a structur (or composite data) consist of * Length prefix * Data string * Terminator

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

so casting will not work

所以铸造将不起作用

回答by Jon

It cannot be, because then the four bytes in memory preceding the LPTSTRwould be considered as the length of the resulting BSTR. This might cause a memory protection fault on the spot (not very likely), but it would certainly result in a BSTRwith a length that could be way larger than the length of the original LPTSTR. So when someone tries to read or write from that they may access invalid memory.

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

回答by sharptooth

No, you cannot - if the code that believes it is a BSTR calls SysStringLen()it will run into undefined behavior since that function relies on some implementation-specific service data.

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

回答by John Dibling

You cannot cast, you must convert. You can use the built-in compiler intrinsic _bstr_t(from comutil.h) to help you do this easily. Sample:

你不能投射,你必须转换。您可以使用内置编译器内在_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;
}

回答by 0xC0000022L

Generally speaking no, but there are ways to make them compatible to some extent via helper classes and macros (see below).

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

The main reason why a 1:1 mapping will never be possible is that a BSTR(and consequently CComBSTRcan contain '\0'in the string, because ultimately it is a counted string type.

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



Your best choice when using C++ would be to go for the ATL class CComBSTRin place of BSTRproper. In either case you can make use of the ATL/MFC conversion macros CW2Aand friends.

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

Also note that the documentation (MSDN) says:

还要注意文档(MSDN)说:

The recommended way of converting to and from BSTRstrings is to use the CComBSTRclass. To convert to a BSTR, pass the existing string to the constructor of CComBSTR. To convert from a BSTR, use COLE2[C]DestinationType[EX], such as COLE2T.

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

... which applies to your use case.

...适用于您的用例。

Please see John Dibling's answer for an alternative (_bstr_t).

请参阅 John Dibling 的答案以获取替代方案 ( _bstr_t)。

回答by Luther

No, you cannot cast them directly. However, you can make a string that does both. A C-String doesn't have a 4-byte header. However, the bit in the middle is the same so if you find yourself needing both representations, make a wrapper class that constructs a string with a 4byte header and a null terminator but can return accessors to the BSTR portion and the C-String.

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

This code is intended as an incomplete example, I haven't compiled this!

这段代码是一个不完整的例子,我还没有编译这个!

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;
};