Reputation: 777
since I can get hands on the new RAD Studio Xe4 I thought I'd give it a try. Unfortunatly, I am not so experienced with C++ and therefore I was wondering why the Code that works perfectly fine in VC++ doesn't work at all in C++ Builder. Most of the problems are converting different var-types. For example :
std::string Test = " ";
GetFileAttributes(Test.c_str());
works in VC++ but in C++ Builder it won't compile, telling me "E2034 Cannot convert 'const char *' to 'wchar_t *'. Am I missing something? What is the reason that doesn't work the same on all compilers the same? Thanks
Upvotes: 0
Views: 2550
Reputation: 14039
You have defined _UNICODE
and/or UNICODE
in Builder and not defined it in VC.
Most Windows APIs come in 2 flavours the ANSI flavour and the UNICODE flavour.
For, when you call SetWindowText
, there really is no SetWindowText
functions. Instead there are 2 different functions
- SetWindowTextA
which takes an ANSI string
and
- SetWindowTextW
which takes a UNICODE string.
If your program is compiled with /DUNICODE /D_UNICODE, SetWindowText
maps to SetWindowTextWwhich expects a
const wchar_t *`.
If your program is compiled without these macros defined, it maps to SetWindowTextA
which takes a const char *
.
The windows headers typically do something like this to make this happen.
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif
Likewise, there are 2 GetFileAttributes
.
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName);
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName);
In VC, you haven't defined UNICODE/_UNICODE & hence you are able to pass string::c_str()
which returns a char *
.
In Builder, you probably have defined UNICODE/_UNICODE & it expects a wchar_t *
.
You may not have done this UNICODE/_UNICODE thing explicitly - may be the IDE is doing it for you - so check the options in the IDE.
You have many ways of fixing this
or
std::w_string
- then c_str()
will return a wchar_t *
or
GetFileAttributesA
directly instead of GetFileAttributes
- you will need to do this for every other Windows API which comes with these 2 variants.Upvotes: 1
Reputation: 14591
Your C++ Builder config is set to use UNICODE character set, which means that Win32 APIs are resolved to their wide character versions. Therefore you need to use wide char strings in your C++ code. If you would set your VS config to use UNICODE, you would get the same error.
You can try this:
// wstring = basic_string<wchar_t>
// _T macro ensures that the specified literal is a wide char literal
std::wstring Test = _T(" ");
GetFileAttributes(Test.c_str()); // c_str now returns const wchar_t*, not const char*
See more details about _T/_TEXT macros here: http://docwiki.embarcadero.com/RADStudio/XE3/en/TCHAR_Mapping
Upvotes: 1
Reputation: 76579
Welcome to Windows Unicode/ASCII hell.
The function
GetFileAttributes
is actually a macro defined to either GetFileAttributesA
or GetFileAttributesW
depending on if you have _UNICODE
(or was it UNICODE
, or both?) defined when you include the Windows headers. The *A
variants take char*
and related arguments, the *W
functions take wchar_t*
and related arguments.
I suggest calling only the wide *W
variants directly in new code. This would mean switching to std::wstring for Windows only code and some well-thought out design choices for a cross-platform application.
Upvotes: 6