0

I'm having a problem returning a native string in the correct character-set. I convert from a string to a wstring to an LPCWSTR to pass back to managed. For the string to wide-string, the s2ws method produces a very small string return because it seems to stop at my first would-be terminator (in managed), which is ';'. So, before you mention s2ws, I've alreday tried it to no avail.

String stuff:

    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());

Later string stuff:

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;

How do I know it's a character set/encoding problem? Well, when the LPCWSTR is returned to managed and I use Marshal to Unicode string, I get a wall of null/empty characters. When I try it in ANSI, this is what I get (reduced in size/scale for readability):

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

The s2ws method is supposed to address the ANSI/UNICODE nightmare that is std::string->std::wstring but that makes the return far too short - far shorter than it should be - but doesn't address the actual charset problem.

Result (to ANSI, again - no reducing done on my part): ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ

When I check in native, wprintf_s shows me that the string is valid/good before the LPCWSTR conversion happens in the export method; so, I need to understand:

  1. Is there a way for me to tell what the byte size of the characters actually are? (I'm thinking that this is an 8byte versus 16byte scenario?)
  2. Since wprintf_s works on the wide string, I checked it against the LPCWSTR and it printed the same (expected) data; so, the issue doesn't appear to be in the .ctor() of the LPCWSTR. Yet, I want to double-check my maths: Am I LPCWSTR'ing correctly?
  3. Since everything in native is telling me that the string is good, how can I check it's character-set (in native)?

The return, itself, is about 8 lines of text, with a delimiter ';' used so that I can split the string in managed and do magic with it. The only issue is getting the string to render as a valid string in managed, with the correct characters in it.

I feel like, maybe, I'm missing something obvious here but I cannot figure out what it is and just need a fresh pair of eyes to tell me where and how I'm failing at life.

4

1 回答 1

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

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

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

假设“托管”您指的是 .NET,那么 .NET 的编组器使用 释放非托管内存CoTaskMemFree(),因此如果您使用默认编组,返回的指针必须指向使用CoTaskMemAlloc()或等效分配的内存(SysAllocString...()例如)。

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

于 2018-11-26T22:57:34.480 回答