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

时间:2018-11-26 22:32:52

标签: c++ string unicode marshalling lpcwstr

我在以正确的字符集返回本地字符串时遇到问题。我将字符串从wstring转换为LPCWSTR以传递回托管。对于从字符串到宽字符串,s2ws method会产生非常小的字符串返回,因为它似乎停止在我的第一个可能的终止符(在托管方式中),即';'处。因此,在您提到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;

我怎么知道这是一个字符集/编码问题?好吧,当LPCWSTR返回到托管状态并且我使用Marshal转换为Unicode字符串时,我得到了一排空/空字符。当我在ANSI中尝试时,这就是我得到的(减小大小/比例以提高可读性):

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

s2ws方法应该解决std :: string-> std :: wstring的ANSI / UNICODE噩梦,但这会使返回值太短-比它应该的短得多-但不能解决实际问题字符集问题。

结果(对于ANSI,再次-我没有做任何减少): ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ

当我签入本机代码时,wprintf_s向我显示在导出方法中发生LPCWSTR转换之前,该字符串有效/正确;所以,我需要了解:

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

返回本身大约有8行文本,并带有定界符';'。用于将字符串拆分为托管字符串并对其进行魔术处理。唯一的问题是让字符串在托管的情况下呈现为有效字符串,并且其中包含正确的字符。

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

1 个答案:

答案 0 :(得分:0)

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

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

要执行您想做的事情,您将必须返回一个指向动态分配的内存的指针,然后接收器将在使用完该内存后释放该内存。

假设“托管”是指.NET,则.NET的编组器使用CoTaskMemFree()释放非托管内存,因此,如果您使用默认的封送处理,则返回的指针必须指向使用{分配的内存。 {1}}或等效值(例如CoTaskMemAlloc())。

否则,如果您没有使用默认的封送处理(即,您手动调用SysAllocString...()),则必须使.NET代码将内存指针传递回C ++代码,以便随后正确释放内存。然后,您的C ++代码可以按您想要的方式分配内存(只要它仍然是动态分配的,这样它就可以在函数返回后继续存在)。