wxString::wc_str() when not in Unicode build Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
Disch
Experienced Solver
Experienced Solver
Posts: 99
Joined: Wed Oct 17, 2007 2:01 am

wxString::wc_str() when not in Unicode build

Post by Disch » Tue Feb 10, 2009 8:22 pm

I'm having a bit of trouble using wxString wc_str when not working with Unicode. Here's a quick sample program I made:

Code: Select all

#include <wx/wx.h>


class MyApp : public wxApp
{
	bool OnInit()
	{
		wxASSERT(sizeof(wxChar) == 1);
		wxASSERT(sizeof(wchar_t) == 2);

		wxString str = wxT("j");
		const wchar_t* buf = str.wc_str(wxConvLocal);

		wxMessageBox(wxString::Format(wxT("%X"),buf[0]));

		return false;
	}
};

IMPLEMENT_APP(MyApp);
In Unicode (after dropping the sizeof(wxChar) assert), I get the expected "6A" output, however when not in Unicode I get "FEEE". What's more, I get FEEE even if I change the character from j to something else (it seems any character produces a very long string of FEEE FEEE FEEE)

Am I using the wrong conversion or something?

I'm on Win2k, VS2002, wx2.8.9

Any ideas? Any help appraciated. Thanks.

User avatar
doublemax
Moderator
Moderator
Posts: 14079
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Tue Feb 10, 2009 8:46 pm

Code: Select all

const wchar_t* buf = str.wc_str(wxConvLocal);
this creates a pointer to a temporary object that is already invalid at the next line

If you put the call in one line, it should work:

Code: Select all

wxMessageBox(wxString::Format(wxT("%X"), ((const wchar_t*)str.wc_str(wxConvLocal))[0])); 
If you want to reuse the converted object, do it like this:

Code: Select all

wxWCharBuffer cbuf = str.wc_str(wxConvLocal);
const wchar_t* buf=cbuf.data();
wxMessageBox(wxString::Format(wxT("%X"),buf[0]));
Use the source, Luke!

User avatar
Disch
Experienced Solver
Experienced Solver
Posts: 99
Joined: Wed Oct 17, 2007 2:01 am

Post by Disch » Tue Feb 10, 2009 9:02 pm

doublemax wrote:this creates a pointer to a temporary object that is already invalid at the next line
I see! Thanks!

Your solution works, but I'm a bit confused as to how that behavior is even possible. Wouldn't any temporary object be destroyed when its scope is lost (which would be as soon as wc_str exits)? How could a temporary object pass a pointer to be dereferenced after its lifetime?

I'm not wording this well -- but like, if you call wc_str directly in the call to Format(), it seems to me that wc_str would end (and thus the temporary object would be destroyed) before Format is actually called.

Well whatever. Clarification would be nice, as that seems extremely strange to me, but I guess it isn't important.

Knowing this, though, I'll have to go back and double-check all my xx_str() function calls to make sure I'm not falling victim to this in other areas x_X


EDIT -

Unless... wxString doesn't really have a version of wc_str that returns const wchar_t* and it's instead casting the wxWCharBuffer to const wchar_t*. Then I guess that makes a whole lot of sense.

If that's the case, the documentation is VERY misleading.

User avatar
doublemax
Moderator
Moderator
Posts: 14079
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Tue Feb 10, 2009 9:23 pm

the compiler will generate code so that the temporary object will only get destroyed after the function call.

so something like this:

Code: Select all

strcpy(somecharbuffer, somewxstring.mb_str(wxConvLocal));
is guaranteed to be safe.
Use the source, Luke!

Post Reply