LPCWSTR Conversion Issue

Started by
8 comments, last by NuclearCarnage 16 years, 3 months ago
Hi, im back. Before you say "search google", i already have and i couldnt find anything which i could use in my case. Basically, im doing another directx program using direct3d and for some reason i can't convert chars or anything for that matter to LPCWSTR. Let's take one function for example:
const char text[6] = "Hello";

    // draw the Hello World text
    dxfont->DrawTextA(NULL,
                      &text,
                      5,
                      &textbox,
                      DT_CENTER | DT_VCENTER,
                      D3DCOLOR_ARGB(255, 255, 255, 255));
I get this: 1>.\code.cpp(228) : error C2664: 'ID3DXFont::DrawTextA' : cannot convert parameter 2 from 'const char (*)[6]' to 'LPCSTR' 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast I've tried absolutely everything, from just putting (LPCWSTR)&text to making a function to convert it and i am so fed up with it. This doesn't just happen with this function, but with any function i want to put a variable into a LPCWSTR parameter. Someone help me please! NuclearCarnage
____________________________Portfolio (under construction) Nastycritter
My tutorial site: Noobic
(my video site is coming soon)
Advertisement
Try passing it the &text[0] instead.
Remove the '&' in front of 'text'.
Although this has nothing to do with your problem, I'd just like to point this out:

LPCWSTR != LPCSTR != LPCTSTR

LPCWSTR = Long Pointer to a Wide STRing
LPCSTR = Long Pointer to a STRing
LPCTSTR = Long Pointer to a (Type) STRing

LPCWSTR is a typedef for wchar_t*. wchar_t is 16-bits on Windows.
LPCSTR is a typedef for char*. char is 8-bits on Windows.
LPCTSTR could mean either LPCWSTR or LPCSTR, depending on your compiler settings. If UNICODE is defined, LPCTSTR resolves to LPCWSTR. Otherwise, it resolves to LPCSTR.
NextWar: The Quest for Earth available now for Windows Phone 7.
well removing the & actually worked for this one but i swear i'd already tried that.

but the more important function which isnt working and is the same problem is this:

const char path [89] = "C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x";	D3DXLoadMeshFromX(path,    // load this file                      D3DXMESH_SYSTEMMEM,    // load the mesh into system memory                      d3ddev,    // the Direct3D Device                      NULL,    // we aren't using adjacency                      &bufMeshMaterial,    // put the materials here                      NULL,    // we aren't using effect instances                      &numMaterials,    // the number of materials in this model                      &meshMesh);    // put the mesh here


and unfortunately removing the & doesn't work for this one :(

its the same error message btw
____________________________Portfolio (under construction) Nastycritter
My tutorial site: Noobic
(my video site is coming soon)
No, it's not the same error message, it's different.

Does D3DXLoadMeshFromXA work (Instead of D3DXLoadMeshFromX)? If so, you have a Unicode vs MBCS issue (See Sc4Freak's post). Either switch to unicode strings or change the project to using the multi-byte character set instead.

I'd also avoid this like the plague:
const char path [89] = .....
If you add one more character to that string, you're writing into random memory. Using a std::string would be better, or doing this:
const char path [] = .....
And let the compiler work out how big the buffer needs to be.
yep ur right D3DXLoadMeshFromXA does work, and thanks for the heads up on the [] thing ;)

one more thing, what are "unicode strings" and how do i use them? :D
____________________________Portfolio (under construction) Nastycritter
My tutorial site: Noobic
(my video site is coming soon)
Quote:Original post by NuclearCarnage
one more thing, what are "unicode strings" and how do i use them? :D
A unicode string is made up from wchat_t's, a non-unicode (multi byte) string is made up from char's. wchat_t's are usually 16-bits wide, char's are usually 8-bit.
By default, VC2005 (And probably 2008, although I haven't checked) uses unicode strings - which is good for localsation and so on, but a lot of tutorials and books only cover multi-byte strings.

To change from unicode to multi-byte strings, goto your project settings (Alt+F7) -> Configuration Properties -> General, and set "Character Set" to "Use Multi-Byte Character Set" (Assuming VC2005).
That causes various functions to default to the non-unicode versions (I won't go into the specifics of what functions or how it does it unless you want me to).
To elaborate a bit on the above answers, the Windows API (including DirectX) comes in two versions.
One for Unicode, and one for the ASCII character set.

Functions such as D3DXLoadMeshFromX are really just macros that call either D3DXLoadMeshFromXA or D3DXLoadMeshFromXW, depending on whether or not UNICODE is defined.
All functions (at least the ones that take string or char arguments, or returns one of those types) have both a -A and a -W version you can call.

In your case, it seems UNICODE is defined, so when you call D3DXLoadMeshFromX, it calls the W version, which expects all string arguments to be wide characters (wchar_t) rather than char's.

You can either call the ASCII version of the function (D3DXLoadMeshFromXA), which will take your char* input, or call D3DXLoadMeshFromX, and give it arguments of the correct type.

This snippet defines a C-style string of char's, or in Win32 terminology, a LPCSTR :
const char path [89] = "C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x";


But the Unicode version of the function you call expects a LPCWSTR, that is, a string of wchar_t's.

To define one of those instead, you have to do:
const wchar_t path [89] = L"C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x";


Or you can go the flexible route, and define the string to be whether fits the current Unicode setting.
Microsoft defines a few helpful macros for that, which give you a LPCTSTR:

const TCHAR path [89] = _T("C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x");

These macros will turn the string into either an ASCII version (of char's) or the Unicode one (wchar_t) depending on whether Unicode is enabled in your project.

In other words, use the first option (plain char strings) if you specifically call the *A version of Windows functions.
Use the second version (wchar_t strings) if you call the *W versions.
And the third one (TCHAR) if you just call the "default" functions (without the A or W postfix)

Ok, now on to another detail. As already said above, save yourself the future bugs and stop using char arrays to store strings.
Assuming you're writing C++ (which seems likely given that you're interfacing with DirectX without any special magic), use C++ strings. They're there for the same.

std::string stores an ASCII string of any length. To get a char array (which Win32 functions expect) out of it, you call the c_str() member function.

std::wstring stores a Unicode string. To get a wchar_t array out of it, you call c_str().

Now, define your strings using those isntead:

const std::string path = "C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x";const std::wstring path = L"C:/Program Files (x86)/Microsoft DirectX SDK (November 2007)/Samples/Media/misc/teapot.x";
thankyou so much, that has helped me enormously and fixed other problems i've been having :D really appreciate it ;)

NuclearCarnage
____________________________Portfolio (under construction) Nastycritter
My tutorial site: Noobic
(my video site is coming soon)

This topic is closed to new replies.

Advertisement