C++ - ExpandEnvironmentStrings Giving Conversion Error - c++

I have been using this:
char appdata[250];
ExpandEnvironmentStrings("%AppData%\\\MCPCModLocator\\", appdata, 250);
in C++ Win32 to get the AppData folder on one of my projects. Its worked fine, no issues. Now on my newest project (same PC, still in Visual Studio 2013) when I try to do that, i get an error on the first string saying "const char* is incompatible with type LPCWSTR" and on the second parameter it says "char * is incompatible with type LPWSTR". I have no idea why it work on the first project, but not the second. I assume its a setting change, but looking through each projects settings, I see nothing. Any help is appreciated! Thanks!

ExpandEnvironmentStrings is a macro that expands to ExpandEnvironmentStringsA or ExpandEnvironmentStringsW depending on whether UNICODE was defined when you included <windows.h>.
In a Visual Studio project UNICODE is defined by default, but this is not so for command line use of the compiler.
Since modern Windows programming is better based on Unicode, the best fix is not to remove the definition of UNICODE but to add an L prefix to your literals, like L"Hello", which makes it a “wide” wchar_t based literal, and correspondingly change the type of appdata.

By default, newly created project in VS2013 has been set to use Unicode APIs, those use LPWSTR (or, wchar_t*) instead of LPSTR(or, char*).
You can call the old ANSI version APIs by add "A" at the end of function name explicitly e.g. ExpandEnvironmentStringsA or change the project configuration to use Multibyte character set(Project Property pages -> configuration properties -> general -> character set)

Related

Set execution character set for Visual C++ compiler

Is it possible to set the execution character set for Visual C++ compiler?
Problem
When trying to convert an (UCN) string literal to a wide string, a runtime crash happens when using Visual Studio 2015 for compilation:
std::string narrowUCN = "\u00E4\u00F6\u00FC\u00DF\u20AC\u0040";
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convertWindows;
std::wstring wide = convertWindows.from_bytes(narrowUCN); // Unhandled C++ exception in xlocbuf, line 426.
Using narrowUCN = u8"\u00E4\u00F6\u00FC\u00DF\u20AC\u0040" works so I assume a problem with the execution character set?
Since Visual Studio 2015 Update 2, it is possible to set the execution character set to UTF-8 using the compiler option /utf-8. Then the conversion of narrow string literals, that don't use u8, will work. This is because those string literals are then converted to UTF-8 instead of the system's codepage (which is the default behaviour of Visual C++ compiler).
The option /utf-8 is a synonym for /source-charset:utf-8 and /execution-charset:utf-8. From the link above:
In those cases where BOM-less UTF-8 files already exist or where changing to a BOM is a problem, use the /source-charset:utf-8 option to correctly read these files.
Use of /execution-charset or /utf-8 can help when targeting code between Linux and Windows as Linux commonly uses BOM-less UTF-8 files and a UTF-8 execution character set.
PS: Don't confuse this with the character set setting in the common project configuration page which only sets the Macros Unicode/MBCS (historical reasons).

Visual Studio 2010 Arduino cpp Error: argument of type "char *" is incompatible with parameter of type "LPCWSTR"

I'm trying to set up an arduino uno for serial port communication with a C++ program in visual studio 2010. I'm working from the code found here: http://playground.arduino.cc/Interfacing/CPPWindows
Unfortunately, the .cpp file gives me the following message for line 9 for the variable 'portName':
Error: argument of type "char *" is incompatible with parameter of type "LPCWSTR"
I don't understand this error message, and have tried a few different things to fix it. Any help would be greatly appreciated!
Given the code link in your question, it seems the problem is here:
Serial::Serial(char *portName)
{
...
this->hSerial = CreateFile(portName, // <--- ERROR
CreateFile is a Win32 API that expects an LPCTSTR as first string parameter .
LPCTSTR is a Win32 typedef, which is expanded to:
const char* in ANSI/MBCS builds
const wchar_t* in Unicode builds (which have been the default since VS2005)
Since you are using VS2010, probably you are in the default Unicode build mode.
Actually, there is no "physical" CreateFile API exposed, but there are two distinct functions: CreateFileA and CreateFileW. The former takes a const char* input string, the latter takes a const wchar_t*.
In Unicode builds, CreateFile is a preprocessor macro expanded to CreateFileW; in ANSI/MBCS builds, CreateFile is expanded to CreateFileA.
So, if you are in Unicode build mode, your CreateFile call is expanded to CreateFileW(const wchar_t*, ...). Since portName is defined as a char*, there is a mismatch between wchar_t* and char*, and you get a compiler error.
To fix that, you have some options.
For example, you could be explicit in your code, and just call CreateFileA() instead of CreateFile(). In this way, you will be using the ANSI/MBCS version of the function (i.e., the one taking a const char*), independently from the actual ANSI/MBCS/Unicode settings in Visual Studio.
Another option would be to change your current build settings from the default Unicode mode to ANSI/MBCS. To do that, you can follow the path:
Project Properties | Configuration Properties | General | Character Set
and select "Use Multi-Byte Character Set", as showed in the following screenshot:
Your settings in Visual Studio are probably set to Unicode but the code you're compiling expects ASCII.
Go to Project Properties -> Configuration Properties -> General -> Character Set and choose "Use Multi-Byte Character Set".
-Surenthar
Your settings in Visual Studio are probably set to Unicode but the code you're compiling expects ASCII.
Go to Project Properties -> Configuration Properties -> General -> Character Set and choose "Use Multi-Byte Character Set".
You should also remove UNICODE or _UNICODE from C++ -> Preprocessor -> Preprocessor definitions, if they are defined there.
This will make your code call the ASCII versions of the Windows API functions, which accept char strings.

No way to solve this without modifying Microsoft header?

Trying to compile this old VC++ 6.0 program in VC++ 2010. This ATL/WTL stuff is giving me lots of problems. I downloaded and have linked to the latest WTL (as far as I know) wtl71.
I am getting compile errors in atlmisc.h:
atlmisc.h(1159): error C2440: 'return' : cannot convert from 'const char *' to 'TCHAR *'
I've searched the 'net, and the answers that come up call for modifying the stock MS atlmisc.h file!
Am I missing something here? What do I need to do to get this to compile?
Most of the time I've seen that error, it's because I've been trying to build a Unicode application. In a Unicode application, the TCHAR* is a short* or wchar_t* rather than a char*.
I'd suggest checking your project settings and making sure that in the project properties, General > Character Set is set to Use Multi-Byte Character Set.

Open file in TagLib with Unicode chars in filename

I am quite new to the C++ 'area' so I hope this will not be just another silly 'C++ strings' question.
Here is my problem. I want to integrate TagLib (1.5, 1.6 as soon as I manage to build it for Windows) into an existing Windows MFC VS2005 project. I need it to read audio files metadata (not write).
The problem is that the program stores the input file names using CString(), and it has the Unicode option turned on (so the default chars are "wchar_t"). The reason for this (I think, the project was started by someone else) is that some of the 'input' file names could contain Unicode charaters (for example, Japanse or Arabic characters).
For example, the file path is something like "d:\docs\audio_test\stragecharڝhere.mp3", but I get it with:
CString fpath = tmpFile->GetFilePath();
Now.. if I try to do:
TagLib::FileRef f(fpath.GetBuffer(0));
fpath.ReleaseBuffer();
I get something like:
unresolved external symbol
"__declspec(dllimport) public:
__thiscall TagLib::FileName::FileName(wchar_t
const *)"
If I try something like:
TagLib::FileRef f(reinterpret_cast<char*>(fpath.GetBuffer(0)));
fpath.ReleaseBuffer();
I get rid of the compilation errors, but "f" is an invalid pointer/object.. and when I try reading a tag, I receive an assert failed.
So, can anyone give me some pointers on how should I pass that CString, in it's Unicode form, to the TagLib ?
Update: TagLib address: http://developer.kde.org/~wheeler/taglib.html
Thank you,
Alex
It's possible that the problem is caused by the issue described here. Basically MSVC has an option to treat the wchar_t type differently, which causes the compiled library is not binary compatible with an application compiled without that option. Unfortunately the CMakeLists.txt build file enables the /Zc:wchar_t- option by default. I'd try to edit the file, remove the option and re-compile TagLib. Ideally version 1.6, as it contains a lot of bug fixes.
I missed something essential when I first read your post, so here is another, new and improved answer:
The error comes from the linker, not the compiler. It thus seems that TagLib::FileName does have a ctor taking wchar_t const*, but the problem is that you don't link with the library implementing it, or link with a version of the library that does not include it.
IIUC, this library comes from the Linux world (where file names are expressed as char arrays), and was later ported to Windows (where file names are expressed as wchar_t arrays). The FileName ctor taking a wchar_t array is thus probably conditionally compiled on Windows (i.e., inside #ifdef _WIN32 or something similar), and the library you are linking with (if you are linking the library) was not compiled with the same preprocessor defines.

Compilation error when calling _tcsstr and assigning to a wchar_t*

I am getting a compilation error when trying to build a C++ project which previously worked.
The code follows:
const wchar_t* pdest;
pdest = _tcsstr(ConnStr, Name);
The error follows:
Error 10 error C2440: '=' : cannot convert from 'const char *' to 'const wchar_t
I'm using Visual Studio 2008. The error message explains the problem well, but I know this program used to compile, what am I doing wrong?
Your code is dangerous. _tcsstr is a TCHAR macro, so it's definition can change depending on whether or not UNICODE is defined. wchar_t is fixed. The error you're seeing is due to this exact problem - the environment is using the single-byte version of _tcsstr (likely becasue UNICODE is not defined).
Don't just define UNICODE. Fix the code first. Either use TCHAR macros for both, or the wide character functions.
_tcsstr is for use with TCHAR. Depending on compile settings, this is either char or wchar_t.
So either use TCHAR, or wcsstr
That should fix this issue:
Property -> Configuration Properties -> General -> Character Set : Use multi-Byte Character Set.