C++:本机到托管字符串转换问题(也许是字符集)?

C++: Native to Managed String Conversion Problem (Maybe Character Set)?

我在 return 以正确的字符集输入本机字符串时遇到问题。我从一个字符串转换为一个 wstring 到一个 LPCWSTR 以传递回托管。对于宽字符串的字符串,s2ws method 生成一个非常小的字符串 return,因为它似乎停止在我的第一个可能的终止符(在托管中),即“;”。所以,在你提到 s2ws 之前,我已经尝试了一天都没有用。

字符串内容:

    char target[1024];
    sprintf_s(target, 1024, "%s %s%s%s",
            mac,
            " (",
            pWLanBssList->wlanBssEntries[t].dot11Ssid.ucSSID,
            ");");
    std::string targetString = std::string(target);
    targetWString.append(targetString.begin(), targetString.end());

后面的字符串内容:

std::wstring returnWString = L"";
returnWString.append(SomeMthod().c_str());
//wprintf_s(returnWString.c_str()); // Works - Data is in the string.
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;

我怎么知道这是字符 set/encoding 问题?好吧,当 LPCWSTR return 被管理并且我使用 Marshal 到 Unicode 字符串时,我得到了一堵 null/empty 字符。当我在 ANSI 中尝试它时,这就是我得到的(为了便于阅读而在 size/scale 中减少):

ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ

s2ws 方法应该解决 ANSI/UNICODE 噩梦,即 std::string->std::wstring 但这使得 return 太短了 - 比它应该的短得多是 - 但没有解决实际的字符集问题。

结果(对 ANSI,再次 - 我没有减少): 设想函函

当我签入 native 时,wprintf_s 显示在导出方法中发生 LPCWSTR 转换之前字符串是 valid/good;所以,我需要明白:

  1. 有没有办法告诉我字符的实际字节大小是多少? (我在想这是 8 字节还是 16 字节的情况?)
  2. 由于 wprintf_s 适用于宽字符串,我根据 LPCWSTR 检查了它,它打印了相同的(预期的)数据;因此,问题似乎不在 LPCWSTR 的 .ctor() 中。然而,我想仔细检查一下我的数学:我的 LPCWSTR 是否正确?
  3. 既然本机中的所有内容都告诉我字符串是好的,我如何检查它的字符集(本机中)?

return 本身大约有 8 行文本,带有分隔符“;”使用这样我就可以在托管中拆分字符串并用它来做魔术。唯一的问题是让字符串呈现为托管中的有效字符串,其中包含正确的字符。

我觉得,也许,我在这里遗漏了一些明显的东西,但我无法弄清楚它是什么,只需要一双新的眼睛来告诉我我在生活中在哪里以及如何失败。

LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;

这是 return 指向数据的指针,当 returnWString 超出范围时,该指针会在 return 之后立即释放。 returned 指针 无效 在接收方甚至可以使用它之前。这是未定义的行为

要执行您正在尝试的操作,您必须 return 一个指向动态分配内存的指针,然后接收方在使用完该内存后必须释放该内存。

假设 "managed" 您指的是 .NET,然后 .NET 的编组器使用 CoTaskMemFree() 释放非托管内存,因此如果您使用默认编组,returned 指针必须指向使用 CoTaskMemAlloc() 或等价物(例如 SysAllocString...())分配的内存。

否则,如果您没有使用默认封送处理(即,您正在手动调用 Marshal.PtrToStringUni()),那么您将不得不让 .NET 代码将内存指针传递回您的 C++ 代码,以便它然后可以正确释放内存。然后您的 C++ 代码可以根据需要分配内存(只要它仍然是动态分配的,这样它就可以在函数 return 之后继续存在)。