C ++: Относительно проблемы преобразования управляемой строки (возможно, набора символов)? - PullRequest
0 голосов
/ 27 ноября 2018

У меня проблема с возвратом нативной строки в правильном наборе символов.Я преобразовываю строку в строку wstring в LPCWSTR, чтобы передать обратно в управляемый.Для строки в широкую строку метод s2ws производит очень малый возврат строки, потому что он, кажется, останавливается на моем первом потенциальном терминаторе (в управляемом), который равен ';'.Итак, прежде чем вы упомянули 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 возвращается к управляемому, и я использую маршал в строку Юникода, я получаю стену из нулевых / пустых символов.Когда я пробую это в ANSI, вот что я получаю (уменьшенный в размере / масштабе для удобства чтения):

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

Предполагается, что метод s2ws решает кошмар ANSI / UNICODE, который является std:: string-> std :: wstring, но это делает возвращение слишком коротким - намного короче, чем должно быть - но не решает проблему реальной кодировки.

Результат (опять же в ANSI - с моей стороны сокращение не выполняется): 101

Когда я проверяю в нативном режиме, wprintf_s показывает мне, что строка действительна / хорошаперед преобразованием LPCWSTR в методе экспорта;Итак, мне нужно понять:

  1. Можно ли мне сказать, каков на самом деле размер символов в байтах?(Я думаю, что это сценарий 8 байт против 16 байт?)
  2. Поскольку wprintf_s работает с широкой строкой, я проверил его по LPCWSTR и напечатал те же (ожидаемые) данные;таким образом, проблема не в .ctor () LPCWSTR.Тем не менее, я хочу перепроверить мою математику: правильно ли я записываю LPCWSTR?
  3. Поскольку все в нативе говорит мне, что строка хорошая, как я могу проверить ее набор символов (в нативном)?

Само возвращение составляет около 8 строк текста с разделителем ';'используется, чтобы я мог разделить строку в управляемом и сделать магию с ним.Единственная проблема заключается в том, чтобы заставить строку отображаться в качестве допустимой строки в управляемом файле с правильными символами.

Мне кажется, что, может быть, я упускаю что-то очевидное здесь, но я не могу понять, что это такоеи просто нужна свежая пара глаз, чтобы сказать мне, где и как я терплю неудачу в жизни.

1 Ответ

0 голосов
/ 27 ноября 2018
LPCWSTR returnLpcuwstr = returnWString.c_str();
return returnLpcuwstr;

Возвращает указатель на данные, которые освобождаются сразу после return, когда returnWString выходит из области видимости.Возвращенный указатель недействителен , прежде чем получатель сможет его использовать.Это неопределенное поведение .

Чтобы сделать то, что вы пытаетесь, вам нужно будет вернуть указатель на динамически распределенную память, а затем получателю придется освободить эту память, когда закончите с его использованием..

Предполагая, что "управляемым" вы ссылаетесь на .NET, маршаллер .NET освобождает неуправляемую память, используя CoTaskMemFree(), поэтому, если вы используете маршалинг по умолчанию, возвращаемый указатель должен указывать на выделенную память.используя CoTaskMemAlloc() или эквивалентный (например, SysAllocString...()).

В противном случае, если вы не используете маршалинг по умолчанию (т. е. вместо этого вы вызываете Marshal.PtrToStringUni() вручную), вам придется сделатьКод .NET передает указатель памяти обратно в ваш код C ++, чтобы затем он мог правильно освободить память.Тогда ваш код C ++ может выделять память по вашему усмотрению (при условии, что она по-прежнему распределяется динамически, так что она может выжить после возврата функции).

...