Skip to main content
GameDev.net gamedev.net
🔒 Locked

VS2005 casting errors

Started by Sevans Jul 12, 2006 at 9:46 PM 9 replies 3.8k views
Original Post
Sevans
Sevans
Hi, I just made the switch from VS2003 to VS2005. I converted a solution from vs2003 to vs2005 and I am now getting errors when it ran fine before. For the following code exerpt: const char g_szClass[] = "FrameClass"; WNDCLASSEX wcex; wcex.lpszClassName = g_szClass; // the class name I get the following errors on build: c:\my files\programming\directx\tutorials\role playing game programming with directx\chapter 6 - page 170 - basic d3d app\basic d3d app\basic d3d app\basic d3d app.cpp(219) : error C2440: '=' : cannot convert from 'const char [11]' to 'LPCWSTR' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast and others all for the same "string to LPCWSTR" casting. Any ideas on why this would be? some type of strict type casting going on? when I do: wcex.lpszClassName = (LPCWSTR)g_szClass; // the class name I get all [] (boxes not brackets) in the text then, this doesnt work so well for me :) Thanks for any ideas you guys got ^^ -sevans
-Sevans
darookie
darookie
In VS2k5 the default character set is UNICODE, as opposed to multi-byte in VS2k3.
You have two valid options (casting is NOT an option here):
1) change the compiler settings to "multibyte character set"
2) use unicode strings (recommended)

Since you only convert an old project and (as I assume) are not interested in localisation, option 1) is the easiest.

HTH,
Pat.
Sevans
Sevans
well if option 2 is advised, I would rather do that now, while my source is only 1 file :) Could you tell me how to do it? I was rather new to vs2003 at the time too. I came from simple code blocks :)

Thanks
-Sevans
BrianL
BrianL
Change your type and prefix your string with an L, as in:

const wchar_t g_szClass[] = L"FrameClass";

MS also provides macros that can handle varying char type settings:

const TCHAR g_szClass[] = _T("FrameClass");

This handles both, but relies on windows headers.
Sevans
Sevans
Thanks guys,

Just to clarify this a bit more for me;
if i started a new Win32 project in VS2005 and then started again from scratch, would I still have to do option 2 (which I am assuming is)
Quote:

Change your type and prefix your string with an L, as in:

const wchar_t g_szClass[] = L"FrameClass";

MS also provides macros that can handle varying char type settings:

const TCHAR g_szClass[] = _T("FrameClass");

This handles both, but relies on windows headers.


or would the problem just dissappear because the text would be in a different format?

-Sevans
darookie
darookie
Quote:
Original post by Sevans
if i started a new Win32 project in VS2005 and then started again from scratch, would I still have to do option 2 (which I am assuming is)
[...]
or would the problem just dissappear because the text would be in a different format?

You would still have to use wchar_t and prefix strings that are to be used with Win32 API functions (and per se only with these) with an "L" to label and declarse them as unicode strings.
The character set of your source code is not affected by the compiler settings, nor does it alter character and string data types such as char or std::string.

As a sidenote, let me explain the issue a little more detailed so you understand what's really going on.
The Win32 API headers defines a macro for each API function that has one or more string arguments or returns a character pointer. The actual implementation exists in two versions - one ASCII and one UNICODE version. These versions are suffixed by a single letter to indicate the string type.
Example:
MessageBox -> the macro you are used to

MessageBoxA -> the ASCII version that you propably know and use, takes char* arguments, e.g. char const * title = "Some Text"

MessageBoxW -> the UNICODE version; same as MessageBoxA, but expects UNICODE input, e.g. wchar_t const * title = L"Some Text"

The header that defines the macro now looks at the character set that is used by examining the macro _UNICODE (or _UNICODE_) and maps the corresponding function:

#ifdef _UNICODE
# define MessageBox MessageBoxA
#else
# define MessageBox MessageBoxW
#endif
The same is done for any struct that contains C-strings.
So far so good. Now why should you prefer Unicode? First of all, since the introduction of Windows NT (which Windows 2000, XP, 2003, and later are build on), the kernel uses UNICODE internally. This means that the ASCII versions convert the input to unicode at some point anyway, so you might as well use it, too.

Secondly, UNICODE avoids any problems with characters that are outside of the default ASCII set (e.g. character values >128), which are otherwise mapped to whatever charset the user has installed. This can lead to problems with non-English OS versions as the extended ASCII character set (128-255) differs slightly from region to region.

Last but not least, the Hungarian Notation used by the Win32 API indicates the type of the data as well. So if the compiler complains about a missing cast, you can easily spot the requested type by looking at its name. For example LPCSTR stand for "Long Pointer [to] Const STRing". The "Long"-part is an artifact from the 16-bit era and can safely be ignored. the const string part tells you that the ASCII character set is used and that the data will not be modified (i.e. const char *).
LPCWSTR, however, is almost the same with the exception that it's a "Wide STRing", e.g. UNICODE.

Hope that clears things up a little,
Pat.
Sevans
Sevans
@Pat: Yeah that helps so much. I did know the difference between ASCII and Unicode but I did not realize the notation difference :) and the fact that it is independent of the source file encoding. This will help a lot in the future.

I will be working away at my code again tomorrow, so this thread may not be dead yet if I run into any problems.

Just another quick question, how standard is it to follow the Win32 API notation. I learned OOP on Java and was always taught with a few minor differences, like always starting with lowercase letters to begin variable and method names. How important would you guys say it is to follow one way or the other (as far as having a nice looking portfolio of code)?

Thanks yet again,
-sevans
-Sevans
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by Sevans
@Pat: Yeah that helps so much. I did know the difference between ASCII and Unicode but I did not realize the notation difference :) and the fact that it is independent of the source file encoding. This will help a lot in the future.

I will be working away at my code again tomorrow, so this thread may not be dead yet if I run into any problems.

Just another quick question, how standard is it to follow the Win32 API notation. I learned OOP on Java and was always taught with a few minor differences, like always starting with lowercase letters to begin variable and method names. How important would you guys say it is to follow one way or the other (as far as having a nice looking portfolio of code)?

Thanks yet again,
-sevans


I'd recommend following the ugly Hungarian notation for dealing directly with Win32 stuff, and run away from it quickly/abstract away from it when you can.

Hungarian notation's only arguable utility for type is for languages that are incredibly type-unsafe (like C). Even then it's questionable, but whatever. Win32 is generally regarded as a mess of C.

Hungarian notation is negatively useful for any language that pretends at type safety or interface abstraction (like C++). Why? Well, ideally you don't need to know the type of something, beyond knowing what interfaces it supports (ignoring those folks that claim that interface is type). So, it just gets in the way.

One thing that C++ does not do is abstract away storage issues. I personally use a Hungarian-ish notation, rather against my ideals, to deal with that. Globals are gFoo. Statics are sFoo. Members are mFoo. Locals are just foo. It's ugly, but it helps.
SiCrane
SiCrane
There are some hard rules about identifier usage in C++: Never use an identifier with two double underscores anywhere inside, never use an identifier starting with an underscore and a capital letter and never use an identifier starting with an underscore in the global scope. Aside from that, it's more important to be consitent inside source files than it is to follow any particular naming standards. Chose a convention and stick with it.

As for hungarian notation, there are a couple of useful articles to read about them: Hungarian Warthogs and Making Wrong Code Look Wrong.
Sevans
Sevans
Awesome thanks.

-sevans
-Sevans
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by SiCrane
There are some hard rules about identifier usage in C++: Never use an identifier with two double underscores anywhere inside, never use an identifier starting with an underscore and a capital letter and never use an identifier starting with an underscore in the global scope. Aside from that, it's more important to be consitent inside source files than it is to follow any particular naming standards. Chose a convention and stick with it.

As for hungarian notation, there are a couple of useful articles to read about them: Hungarian Warthogs and Making Wrong Code Look Wrong.


I agree completely with the warts article.

I do have a big issue with Joel's approach in his article, though, and it goes like this: He suggests that a naming convention is the right way to fix a fundamental type break. I'd say the "correct" way to handle two different types of things is to have them be two different (gasp) types.

So, for his example, you have a String class, and an UnsafeString class, and the two aren't implicitly convertible. You have your Request() function return an UnsafeString, which Write() wouldn't accept. Your Encode() function would take an UnsafeString, and return a String, which Write() would accept.

Now, instead of some poor sleepy human being responsible for catching whether or not some variable is "s" or "us", the compiler will helpfully point out that the String and UnsafeString things aren't really the same.

Ironically, I do agree with his fundamental (if somewhat lost in the article) point that, wherever possible, bad code should fundamentally stick out like a sore thumb. I would just argue that, wherever possible, the bad code should be obvious to a compiler so it can remind you when you miss it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.