【问题标题】:How do you convert a 'System::String ^' to 'TCHAR'?如何将“System::String ^”转换为“TCHAR”?
【发布时间】:2011-04-14 17:14:06
【问题描述】:

我问了一个问题here,涉及 C++ 和 C# 通信。问题解决了,但又引出了一个新问题。

这会返回一个字符串 (C#)

return Marshal.PtrToStringAnsi(decryptsn(InpData));

这需要一个 TCHAR* (C++)

lpAlpha2[0] = Company::Pins::Bank::Decryption::Decrypt::Decryption("123456");

我已经用谷歌搜索了如何解决这个问题,但我不确定为什么字符串上有一个胡萝卜(^)。最好将返回从 String 更改为 C++ 可以接受的其他内容吗?还是我需要在分配值之前进行转换?

【问题讨论】:

  • re:你的标志——你需要给 team@stackoverflow 发邮件寻求帮助。另外,吸取的教训?

标签: visual-studio-2010 visual-c++ casting c++-cli tchar


【解决方案1】:

String 有一个^,因为这是托管引用的标记。基本上,它在非托管区域中的使用方式与* 相同,只是它只能指向一个对象类型,不能指向其他指针类型或void。

TCHAR 是 #defined(或者可能是 typedefed,我不记得了)到 charwchar_t,基于 _UNICODE 预处理器定义。因此,我会使用它并编写两次代码。

内联:

TCHAR* str;
String^ managedString
#ifdef _UNICODE
str = (TCHAR*) Marshal::StringToHGlobalUni(managedString).ToPointer();
#else
str = (TCHAR*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();
#endif

// use str.

Marshal::FreeHGlobal(IntPtr(str));

或者作为一对转换方法,两者都假设输出缓冲区已经分配并且足够大。方法重载应该让它根据 TCHAR 的定义选择正确的方法。

void ConvertManagedString(String^ managedString, char* outString)
{
    char* str;
    str = (char*) Marshal::StringToHGlobalAnsi(managedString).ToPointer();    
    strcpy(outString, str);    
    Marshal::FreeHGlobal(IntPtr(str));
}

void ConvertManagedString(String^ managedString, wchar_t* outString)
{
    wchar_t* str;
    str = (wchar_t*) Marshal::StringToHGlobalUni(managedString).ToPointer();    
    wcscpy(outString, str);    
    Marshal::FreeHGlobal(IntPtr(str));
}

【讨论】:

  • 和 Blindy 一样的问题,HGLOBALs 是不透明的结构,应该传递给GlobalLock 以获得指向内容的指针。
  • 如果是这样,那么微软的文档是错误的。 msdn.microsoft.com/en-us/library/…
  • 好的,如果 MEM_FIXED 被传递给 GlobalAllocGlobalLock 是空操作。但是 MSDN 没有说明 StringToHGlobalAnsi 在内部使用什么标志。依赖示例,就好像它们是规范的一部分一样是一个臭名昭著的坏主意。
【解决方案2】:

String^ 的语法是 C++/CLI 讨论“(垃圾收集)对 System.String 的引用”。

您有几个选项可以将String 转换为C 字符串,这是表达TCHAR* 的另一种方式。我在 C++ 中的首选方式是将转换后的字符串存储为 C++ 字符串类型,std::wstringstd::string,具体取决于您将项目构建为 Unicode 还是 MBCS 项目。

在任何一种情况下,您都可以使用以下内容:

std::wstring tmp = msclr::interop::marshal_as<std::wstring>( /* Your .NET String */ );

std::string tmp = msclr::interop::marshal_as<std::string>(...);

将字符串转换为正确的宽或窄字符串格式后,您就可以使用 c_str() 函数访问其 C 字符串表示形式,如下所示:

callCFunction(tmp.c_str());

假设 callCFunction 期望您将 C 风格的 char*wchar_t* 传递给它(TCHAR* 将根据您的编译设置“降级”。

【讨论】:

  • 这两个标准都说 wstring 或 string 不是标准的成员。我错过了种类的参考吗?
  • 您需要在您的 C++ 代码中 #include &lt;string&gt; 才能获得两者的声明。
【解决方案3】:

这是一种非常漫无边际的提问方式,但如果您的意思是如何将 String ^ 转换为 char *,那么您使用之前使用的相同编组器,只是向后:

char* unmanagedstring = (char *) Marshal::StringToHGlobalAnsi(managedstring).ToPointer();

编辑:不要忘记在使用 Marshal::FreeHGlobal 完成后释放分配的内存。

【讨论】:

  • HGLOBAL 不是char*,不应强制转换为一个。要从HGLOBAL 中取出指针,请使用GlobalLock。更好的是,完全避免HGLOBAL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
  • 1970-01-01
相关资源
最近更新 更多