开发者

Returning a dynamic C style string from a function?

Basically I have a function that roughly looks like this and I need to return out.

const char* UTF16ToUTF8(const wchar_t *in) {
    int tmp = wcslen(in);
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, &in[0], (size_t)tmp, 开发者_StackOverflow社区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];
}

Obviously out gets dereferenced when returning. What are my options? I need to be able to call this function like so. I would absolutely love to stay on the stack.

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


Don't trouble yourself with any such worries and return an 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())
}

Then, in your C interface, use:

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

I would even make the argument of the function std::wstring and extract the C-string only when calling the API function.

The begin/end version includes all characters, the .data() version treats the buffer as a null-terminated string. Pick whichever is most appropriate.


Returning std::string would be my first choice.

However if you absolutely, positively need a char*, you have several options.

You could allocate a new char* on the heap and return that, being really, really careful to make sure that the caller always deallocates the memory. I believe there is a boost auto_ptr equivalent that is array friendly that would make explicit this ownership transfer.

Another option is for the caller to pass in the char* (and max size), and the function to put data in there. Thus the caller always owns the memory.

Another option is for the caller to pass in a char** (or char*&), and your function allocates memory to the caller's pointer. This makes the ownership transfer explicit. (you could also have a size (size_t&) parameter to hold the size, if it's something the caller is likely to need).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜