0

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

4

3 回答 3

6

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.

于 2013-04-23T14:51:07.870 回答
1

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

于 2013-04-23T14:52:04.590 回答
1

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 aconst 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

  • find the UNICODE/_UNICODE option in the IDE and disable it.

or

  • use std::w_string - then c_str() will return a wchar_t *

or

  • Call GetFileAttributesA directly instead of GetFileAttributes - you will need to do this for every other Windows API which comes with these 2 variants.
于 2013-04-23T14:52:04.697 回答