Возвращать динамическую строку в стиле C из функции? - PullRequest
2 голосов
/ 05 сентября 2011

В основном у меня есть функция, которая выглядит примерно так, и мне нужно вернуться.

const char* UTF16ToUTF8(const wchar_t *in) {
    int tmp = wcslen(in);
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, &in[0], (size_t)tmp, NULL, 0, NULL, NULL);
    std::vector<char> out;
    out.resize(size_needed);
    WideCharToMultiByte(CP_UTF8, 0,  &in[0], (size_t)tmp, &out[0], size_needed, NULL, NULL);

    return &out[0];
}

Очевидно, что при возврате из него происходит разыменование. Какие у меня варианты? Мне нужно иметь возможность вызывать эту функцию так. Я бы очень хотел остаться в стеке.

utf8outputfile << UTF16ToUTF8(wchar_tString) << endl;
fprintf(utf8outputfile, "%s", UTF16ToUTF8(L"Mmm Mmm Unicode String κόσμε"));
return UTF16ToUTF8(wchar_tString);

Ответы [ 2 ]

6 голосов
/ 05 сентября 2011

Не беспокойтесь такими заботами и верните std::string:

std::string UTF16ToUTF8(const wchar_t *in) {
  std::vector<char> out;
  //...
  return std::string(out.begin(), out.end());  // or std::string(out.data())
}

Затем, в вашем интерфейсе C, используйте:

printf("%s", UTF16ToUTF8(ws).c_str());

Я бы даже сделал аргумент функции std::wstring и извлекал бы C-строку только при вызове функции API.

Версия begin/end включает все символов, версия .data() обрабатывает буфер как строку с нулевым символом в конце Выберите тот, который наиболее подходит.

2 голосов
/ 05 сентября 2011

Возвращение std :: string будет моим первым выбором.

Однако, если вам абсолютно необходим положительный символ *, у вас есть несколько вариантов.

Вы можете выделить новый символ * накучи и возвращаем, что, будучи действительно, действительно осторожно, чтобы убедиться, что вызывающий всегда освобождает память.Я полагаю, что есть улучшенный эквивалент auto_ptr, дружественный к массиву, который бы явно указывал эту передачу прав собственности.

Другой вариант - для вызывающей стороны передавать char * (и максимальный размер) и функцию для помещения данныхтам.Таким образом, вызывающая сторона всегда владеет памятью.

Другой вариант - вызывающая сторона передает символ ** (или символ * &), и ваша функция выделяет память для указателя вызывающей стороны.Это делает передачу права собственности явной.(у вас также может быть параметр size (size_t &) для хранения размера, если он может понадобиться вызывающей стороне).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...