3

I'll start by saying I know basically nothing about wide strings and Unicode support. I let QString and QFile handle that for me 99% of the time, but I'm trying to compile someone else's library written for VC6.

When I compile with MSVC2010 in Qt Creator I get this error:

error: C2664: 'FindFirstFileW' : cannot convert parameter 1 from 'const char *' to 'LPCWSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

The code is using the FindFirstFile function, which is overloaded (sort of) depending on whether you're compiling with the Unicode character set. I don't understand what type FindFirstFile is expecting, when the input for FindFirstFileA and FindFirstFileW seems to be two completely different types.

So here's my question: What is the expected input type for FindFirstFile?

Corollary: How do I take a filename of type const char* and put it into a form that FindFirstType will accept?

Phlucious
  • 3,704
  • 28
  • 61
  • That's not overloading. That's a macro to select one of two differently named functions. C has no overloading. – chris Jul 08 '13 at 20:00
  • Okay, I'll change the phrasing to reflect that. FYI, my input to the function is a character array, not a string literal, so tacking on `L` doesn't help. – Phlucious Jul 08 '13 at 20:01
  • 2
    If you need the code to work when compiled with or without the `UNICODE` preprocessor symbol (you probably don't), replace the call with `FindFirstFile(_T("arg_0"), ...)`. Otherwise, replace the call with `FindFirstFileW(L"arg_0", ...)`. To answer your question, the expected argument type is `const char *` if you're calling `FindFirstFileA` and `const wchar_t *` if you're calling `FindFirstFileW`. – Praetorian Jul 08 '13 at 20:02
  • Hint: Don't get caught up in `TCHAR`s. Use wide strings from the beginning and it's a lot less to worry about and will work in any version of Windows that's not really really old. – chris Jul 08 '13 at 20:04
  • @chris or use UTF-8 everywhere and only convert when necessary: http://www.utf8everywhere.org/ although yours is the most practical advice. – Mark Ransom Jul 08 '13 at 20:15

2 Answers2

8

FindFirstFile is a macro defined as follows:

#ifdef UNICODE
#define FindFirstFile  FindFirstFileW
#else
#define FindFirstFile  FindFirstFileA
#endif // !UNICODE

What this means is that it expands to the one with a W when compiled with UNICODE defined, and it expands to the one with an A otherwise.

Now, FindFirstFile's first parameter is either LPCSTR or LPWCSTR. LPCSTR is a typedef for const char* while LPWCSTR is a typedef for const wchar_t*. In your error message, you try passing a type of const char* as the first argument to FindFirstFileW which takes an argument of type const wchar_t*, hence the error.

In order for the types to match up, you need to pass an object of type const wchar_t*, you have several options:

std::wstring path1 = L"..."; // 1
const wchar_t* path2 = L"..."; // 2
wchar_t path3[] = L"..."; // 3

WIN32_FIND_DATA  w32fd;
FindFirstFile(path1.c_str(), &w32fd); // 1
FindFirstFile(path2, &w32fd); // 2
FindFirstFile(path3, &w32fd); // 3
FindFirstFile(L"...", &w32fd);

How do I take a filename of type const char* and put it into a form that FindFirstType will accept?

If your filename only contains characters in the basic ASCII character set, then you can convert it to a std::wstring like the following: std::wstring path(std::begin(filename), std::end(filename));. Otherwise, you would need to use MultiByteToWideChar or many of the options shown here. Another option would be to call FindFirstFileA directly, but if you are on windows, it generally would be better to use wchar_t to begin with.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
0

The expected input type is const wchar_t* if you are compiling for unicode. (Which you are: the 'W' tells us that.). The expected input type is const char* if you are not compiling for unicode. Before solving your problem you have to decide whether to compile for unicode or not. If you opt for unicode then your strings should be wchar_t* or std::wstring or CString. That should make your problem go away.

If you actually need to use a const char* in a unicode-compiled app then you have to convert the const char* into a const wchar_t* string by calling the MultiByteToWideChar API function.

ScottMcP-MVP
  • 10,337
  • 2
  • 15
  • 15