How to convert string to wchar* in unicode - c++

I'm trying to define a function like this:
#ifdef _UNICODE
LPCTSTR A2T(const string& str);
#else
#define A2T
#endif
If my project is in Ansi, than A2T(str) is str itself. When my project is in unicode A2T(str) return a LPCTST type

When UNICODE is defined, LPCTSTR is an alias for const wchar_t*, otherwise it is an alias for const char*.
Your current macro returns const wchar_t* for Unicode, but returns std::string for Ansi. That doesn't make sense. You wouldn't be able to use A2T() consistently everywhere LPCTSTR is expected. The code would not even compile for Ansi since a std::string cannot be assigned directly to a char*. For Unicode, the code would compile, but you would have a memory leak since a conversion from std:string to wchar_t* requires a dynamic memory allocation that you have to free eventually.
A better option is to have A2T() return std::wstring for Unicode, and std::string for Ansi:
#ifdef UNICODE
std::wstring A2T(const string& str)
{
std::wstring result;
// do the conversion from Ansi to Unicode as needed...
// MultiByteToWideChar(), std::wstring_convert, etc...
return result;
}
#else
std::string A2T(const string& str)
{
return str;
}
#endif
Alternatively:
std::basic_string<TCHAR> A2T(const string& str)
{
#ifdef UNICODE
std::wstring result;
// do the conversion from Ansi to Unicode as needed...
// MultiByteToWideChar(), std::wstring_convert, etc...
return result;
#else
return str;
#endif
}
Either way, you get the automatic memory management you need after conversion, and you can use A2T() consistently in both Ansi and Unicode (when passing the return value of A2T(str) to a LPCTSTR, you can use A2T(str).c_str()).
Or, you could simply forget writing your own function and just use the existing A2CT() function or CA2CT class that is already available in MFC/ATL:
ATL and MFC String Conversion Macros

Related

converting between const wchar_t* and const char* and the reverse using macros

I'm trying to make my win32 program interchangeable between character sets (Unicode and Multi-Byte) the macros such as CreateWindowEx() use wchar_t* and char* depending on the set and for my class name I have it stored in a variable in a windowClass Class.
static constexpr const wchar_t* wndClassName = L"windowclass";
at the moment for other functions I've been using macros I have created defined in a header file
#pragma once
#include <sstream>
#ifdef _UNICODE
#define ConstString(constStringIn) (std::wstringstream() << constStringIn).str().c_str() //used as arguments in functions
#define STRINGALIASMACRO wchar_t* //Used as function return tpyes and wndClassName
#endif // _UNICODE
#ifdef _MBCS
#define ConstString(constStringIn) (std::stringstream() << constStringIn).str().c_str()
#define STRINGALIASMACRO char*
#endif // _MBCS
when trying to replace the wchar_t* with STRINGALIASMACRO and ConstString("windowclass") for the wndClassName variable value the error expression must have a constant value
What could I do to fix this and is it good practice to use macros as type definitions and return types instead of e.g typedef wchar_t* STRINGALIAS I did try this and I got a whole bunch of other errors.
The Win32 API (and the C runtime library) already provide their own sets of preprocessor macros for this exact purpose. Look at:
TCHAR/_TCHAR = char or wchar_t
LP(C)TSTR = (const) char* or (const) wchar_t*
TEXT("literal")/_T("literal") = "literal" or L"literal"
TEXT('literal')/_T('literal') = 'literal' or L'literal'
For example:
#pragma once
#include <windows.h>
#define ConstString(constStringIn) TEXT(constStringIn) //used as arguments in functions
typedef LPTSTR STRINGALIASMACRO; //Used as function return tpyes and wndClassName
typedef LPCTSTR CONSTSTRINGALIASMACRO; //Used as function return tpyes and wndClassName
static constexpr CONSTSTRINGALIASMACRO wndClassName = ConstString("windowclass");
Or simply:
static constexpr LPCTSTR wndClassName = TEXT("windowclass");
See the following for more details:
Win32 Data Types
Working With Strings
Generic-Text Mappings in tchar.h
What are TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR (etc.)?

Converting from const char * to LPTSTR without USES_CONVERSTION

I am trying to convert const char * to LPTSTR. But i do not want to use USES_CONVERSION to perform that.
The following is the code i used to convert using USES_CONVERSION. Is there a way to convert using sprintf or tcscpy, etc..?
USES_CONVERSION;
jstring JavaStringVal = (some value passed from other function);
const char *constCharStr = env->GetStringUTFChars(JavaStringVal, 0);
LPTSTR lpwstrVal = CA2T(constCharStr); //I do not want to use the function CA2T..
LPTSTR has two modes:
An LPWSTR if UNICODE is defined, an LPSTR otherwise.
#ifdef UNICODE
typedef LPWSTR LPTSTR;
#else
typedef LPSTR LPTSTR;
#endif
or by the other way:
LPTSTR is wchar_t* or char* depending on _UNICODE
if your LPTSTR is non-unicode:
according to MSDN Full MS-DTYP IDL documentation, LPSTR is a typedef of char *:
typedef char* PSTR, *LPSTR;
so you can try this:
const char *ch = "some chars ...";
LPSTR lpstr = const_cast<LPSTR>(ch);
USES_CONVERSION and related macros are the easiest way to do it. Why not use them? But you can always just check whether the UNICODE or _UNICODE macros are defined. If neither of them is defined, no conversion is necessary. If one of them is defined, you can use MultiByteToWideChar to perform the conversion.
Actually that's a silly thing to do. JNIEnv alreay has a method to get the characters as Unicode: JNIEnv::GetStringChars. So just check for the UNICODE and _UNICODE macros to find out which method to use:
#if defined(UNICODE) || defined(_UNICODE)
LPTSTR lpszVal = env->GetStringChars(JavaStringVal, 0);
#else
LPTSTR lpszVal = env->GetStringUTFChars(JavaStringVal, 0);
#endif
In fact, unless you want to pass the string to a method that expects a LPTSTR, you should just use the Unicode version only. Java strings are stored as Unicode internally, so you won't get the overhead of the conversion, plus Unicode strings are just better in general.

How do I convert an ATL/MFC CString to a QString?

Given the encoding of the project is probably Unicode (but not for sure) what is the best way of converting ATL::CString to QString?
What I have thought of is this:
CString c(_T("SOME_TEXT"));
//...
std::basic_string<TCHAR> intermediate((LPCTSTR)c);
QString q;
#ifdef _UNICODE
q = QString::fromStdWString(intermediate);
#else
q = QString::fromStdString(intermediate);
#endif
Do you think that it works? Any other ideas?
You don't need the intermediate conversion to a std::string. The CString class can be treated as a simple C-style string; that is, an array of characters. All you have to do is cast it to an LPCTSTR.
And once you have that, you just need to create the QString object depending on whether the characters in your CString are of type char or wchar_t. For the former, you can use one of the standard constructors for QString, and for the latter, you can use the fromWCharArray function.
Something like the following code (untested, I don't have Qt installed anymore):
CString c(_T("SOME_TEXT"));
QString q;
#ifdef _UNICODE
q = QString::fromWCharArray((LPCTSTR)c, c.GetLength());
#else
q = QString((LPCTSTR)c);
#endif
Edit: As suggested in the comments, you have to disable "Treat wchar_t as a built-in type` in your project's Properties to get the above code to link correctly in Visual Studio (source).
For _UNICODE, I believe you could also use the fromUtf16 function:
CString c(_T("SOME TEXT"));
QString q = QString::fromUtf16(c.GetBuffer(), c.GetLength());

How do I convert from std::wstring _TCHAR []?

I'm using a library and sends me std::wstring from one of its functions, and another library that requires _TCHAR [] to be sent to it. How can I convert it?
Assuming you're using Unicode build, std::wstring.c_str() is what you need. Note that c_str() guarantees that the string it returns is null-terminated.
e.g.
void func(const wchar_t str[])
{
}
std::wstring src;
func(src.c_str());
If you're using non-Unicode build, you'll need to convert the Unicode string to non Unicode string via WideCharToMultiByte.
As #Zach Saw said, if you build only for Unicode you can get away with std::wstring.c_str(), but conteptually it would be better to define a tstring (a typedef for std::basic_string<TCHAR>) so you can safely use this kind of string flawlessly with all the Windows and library functions which expect TCHARs1.
For additional fun you should define also all the other string-related C++ facilities for TCHARs, and create conversion functions std::string/std::wstring <=> tstring.
Fortunately, this work has already been done; see here and here.
Actually no compiled library function can really expect a TCHAR *, since TCHARs are resolved as chars or wchar_ts at compile time, but you got the idea.
Use the ATL and MFC String Conversion Macros. This works regardless of whether you are compiling in _UNICODE or ANSI mode.
You can use these macros even if you aren’t using MFC. Just include the two ATL headers shown in this example:
#include <string>
#include <Windows.h>
#include <AtlBase.h>
#include <AtlConv.h>
int main()
{
std::wstring myString = L"Hello, World!";
// Here is an ATL string conversion macro:
CW2T pszT(myString.c_str());
// pszT is now an object which can be used anywhere a `const TCHAR*`
// is required. For example:
::MessageBox(NULL, pszT, _T("Test MessageBox"), MB_OK);
return 0;
}

Any side effect of not using USES_CONVERSION

Recently I made a utilities function like:
// T2CA
#include "ATLCONV.H"
std::string Utils::CString2String(const CString& cString)
{
#if _MSC_VER > 1200
// Convert a TCHAR string to a LPCSTR
// construct a std::string using the LPCSTR input
CT2CA tmp(cString);
std::string strStd (tmp);
#else
// Deprecated in VC2008.
// construct a std::string using the LPCSTR input
std::string strStd (T2CA (cString));
#endif
return strStd;
}
I did several simple tests and it seems to work fine. However, when I search the web I can see that most usages of T2CA in VC6 have a preceding call of
USES_CONVERSION;
Is there anything that I had missed? Should I invoke my function by :
#else
// Deprecated in VC2008.
// construct a std::string using the LPCSTR input
USES_CONVERSION;
std::string strStd (T2CA (cString));
#endif
In ATL 7.0 USES_CONVERSION is not required anymore. Before that you needed to specify the USES_CONVERSION macro or else you'd get compile errors.