C++: How to convert a Unsigned char array to a CString by value, not ASCII

Viewed 101

I would appreciate a little help fixing a bug I have with the conversion of some point data I have that is currently in a unsigned character array (Technically a vector) to a CString.

Currently my code converts the data like this:

std::vector <unsigned char> points;
CString strResult;
int totalpoints = 0;
// Add point data in here (x,y)
// Tick up totalpoints
strResult = CString(reinterpret_cast<char*>(&points[0]), totalpoints * 4); // I did not write this line. I'm just trying to fix it

return strResult.AllocSysString();

The issue arises when something attempts to read the data back out of strResult. Some of the data changes. I believe this is because when CString converts chars it try's to make the same character in wide format, even if the underlying value is different.. For example if I pass it the value 147 I will instead see the value 8339. I can get the value 147 from 8339 if I cast it back into a unsigned char, but where this data ultimately goes I don't have control of it. It is expected that they will get 147 with out casting, not 8339.

So The question is, how do I change the conversion to fix this?

Update: I have been examine the hex values and when the values ending up being incorrect, it's because the high byte in the CString is set to 0x20

Update 2: It might also help clarify that existing data starts as two ints. One for x and one for y. They are separated into pairs of Bytes and stored into points.

1 Answers

0x4D (dec 77) is in the ASCII range (it is the character 'M'), so it should stay the same value when converted to Unicode codepoint U+004D in a wide format.

0x14B (dec 331), on the other hand, doesn't fit in an unsigned char to begin with.

0x93 (dec 147) fits in an unsigned char, but is outside of the ASCII range, so it is subject to charset interpretation, as many different charsets map 0x93 to different Unicode codepoints.

For example, Unicode codepoint U+201C (dec 8220) is indeed encoded as 0x93 in many charsets, such as all of the Windows-125x charsets, but is a different value in other charsets, typically 0xAA (dec 170) but not always.

In general, you need to know the charset that the char data was encoded in, to be able to convert it into a wide format without data loss. But the values may change, yes. That is expected behavior during a conversion between encodings.

CString does not allow you to specify the charset to use when converting char data to a wide format. It always uses the user's default charset. If you know the exact charset used for the char data, use MultiByteToWideChar() or equivalent to convert the data to a wide format before then assigning the result to CString.


Based on new information, you should NOT be casting your vector data to char* at all. You are trying to store binary data into a BSTR (why?). Try something more like this instead:

std::vector <unsigned char> points;
// fill points as needed...

CString strResult;
auto* buf = strResult.GetBufferSetLength(points.size());
std::copy(points.begin(), points.end(), buf);
strResult.ReleaseBuffer();

return strResult.AllocSysString();
Related