How to convert char* to wchar_t*?

C++WinapiUnicodeMingwType Conversion

C++ Problem Overview


I've tried implementing a function like this, but unfortunately it doesn't work:

const wchar_t *GetWC(const char *c)
{
    const size_t cSize = strlen(c)+1;
    wchar_t wc[cSize];
    mbstowcs (wc, c, cSize);

    return wc;
}

My main goal here is to be able to integrate normal char strings in a Unicode application. Any advice you guys can offer is greatly appreciated.

C++ Solutions


Solution 1 - C++

In your example, wc is a local variable which will be deallocated when the function call ends. This puts you into undefined behavior territory.

The simple fix is this:

const wchar_t *GetWC(const char *c)
{
    const size_t cSize = strlen(c)+1;
    wchar_t* wc = new wchar_t[cSize];
    mbstowcs (wc, c, cSize);

    return wc;
}

Note that the calling code will then have to deallocate this memory, otherwise you will have a memory leak.

Solution 2 - C++

Use a std::wstring instead of a C99 variable length array. The current standard guarantees a contiguous buffer for std::basic_string. E.g.,

std::wstring wc( cSize, L'#' );
mbstowcs( &wc[0], c, cSize );

C++ does not support C99 variable length arrays, and so if you compiled your code as pure C++, it would not even compile.

With that change your function return type should also be std::wstring.

Remember to set relevant locale in main.

E.g., setlocale( LC_ALL, "" ).

Solution 3 - C++

const char* text_char = "example of mbstowcs";
size_t length = strlen(text_char );

Example of usage "mbstowcs"

std::wstring text_wchar(length, L'#');

//#pragma warning (disable : 4996)
// Or add to the preprocessor: _CRT_SECURE_NO_WARNINGS
mbstowcs(&text_wchar[0], text_char , length);

Example of usage "mbstowcs_s"

Microsoft suggest to use "mbstowcs_s" instead of "mbstowcs".

Links:

Mbstowcs example

mbstowcs_s, _mbstowcs_s_l

wchar_t text_wchar[30];

mbstowcs_s(&length, text_wchar, text_char, length);

Solution 4 - C++

You're returning the address of a local variable allocated on the stack. When your function returns, the storage for all local variables (such as wc) is deallocated and is subject to being immediately overwritten by something else.

To fix this, you can pass the size of the buffer to GetWC, but then you've got pretty much the same interface as mbstowcs itself. Or, you could allocate a new buffer inside GetWC and return a pointer to that, leaving it up to the caller to deallocate the buffer.

Solution 5 - C++

The question has several problems, but so do some of the answers. The idea of returning a pointer to allocated memory "and leaving it up to the caller to de-allocate" is asking for trouble. As a rule the best pattern is always to allocate and de-allocate within the same function. For example, something like:

wchar_t* buffer = new wchar_t[get_wcb_size(str)];
mbstowcs(buffer, str, get_wcb_size(str) + 1);
...
delete[] buffer;

In general, this requires two functions, one the caller calls to find out how much memory to allocate and a second to initialize or fill the allocated memory. Unfortunately, the basic idea of using a function to return a "new" object is problematic -- not inherently, but because of the C++ inheritance of C memory handling. Using C++ and STL's strings/wstrings/strstreams is a better solution, but I felt the memory allocation thing needed to be better addressed.

Solution 6 - C++

Your problem has nothing to do with encodings, it's a simple matter of understanding basic C++. You are returning a pointer to a local variable from your function, which will have gone out of scope by the time anyone can use it, thus creating undefined behaviour (i.e. a programming error).

Follow this Golden Rule: "If you are using naked char pointers, you're Doing It Wrong. (Except for when you aren't.)"

I've previously posted some code to do the conversion and communicating the input and output in C++ std::string and std::wstring objects.

Solution 7 - C++

I did something like this. The first 2 zeros are because I don't know what kind of ascii type things this command wants from me. The general feeling I had was to create a temp char array. pass in the wide char array. boom. it works. The +1 ensures that the null terminating character is in the right place.

char tempFilePath[MAX_PATH] = "I want to convert this to wide chars";
	
int len = strlen(tempFilePath);

// Converts the path to wide characters
	int needed = MultiByteToWideChar(0, 0, tempFilePath, len + 1, strDestPath, len + 1);

Solution 8 - C++

> Andrew Shepherd 's answer.

Andrew Shepherd 's answer is Good for me, I add up some fix : 1, remove the ending char L'\0', casue sometime it will trouble. 2, use mbstowcs_s

std::wstring wtos(std::string& value){
	const size_t cSize = value.size() + 1;

	std::wstring wc;
	wc.resize(cSize);

	size_t cSize1;
	mbstowcs_s(&cSize1, (wchar_t*)&wc[0], cSize, value.c_str(), cSize);

	wc.pop_back();

	return wc;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAutoBotAMView Question on Stackoverflow
Solution 1 - C++Andrew ShepherdView Answer on Stackoverflow
Solution 2 - C++Cheers and hth. - AlfView Answer on Stackoverflow
Solution 3 - C++MaksView Answer on Stackoverflow
Solution 4 - C++Greg HewgillView Answer on Stackoverflow
Solution 5 - C++CleverhansView Answer on Stackoverflow
Solution 6 - C++Kerrek SBView Answer on Stackoverflow
Solution 7 - C++Gandalf458View Answer on Stackoverflow
Solution 8 - C++Liang August YuningView Answer on Stackoverflow