How would I take...
string modelPath = "blah/blah.obj"
and concatenate it with...
L" not found."
While passing it in as LPCWSTR. I tried to do
(LPCWSTR)(modelPath + " was not found.").c_str()
However that did not work. Here is a larger example of what it looks like now.
if(!fin)
{
MessageBox(0, L"Models/WheelFinal.txt not found.", 0, 0); //
return;
}
LPCWSTR is a L ong P ointer to a C onstant W ide STR ing. Wide strings, at least in Win32, are 16 bits, whereas (const) char strings (i.e. (C)STR or their pointer-counterparts LP(C)STR) are 8 bits.
Think of them on Win32 as typedef const char* LPCSTR and typedef const wchar_t* LPCWSTR.
std::string is an 8-bit string (using the underlying type char by default) whereas std::wstring is a wider character string (i.e. 16-bits on win32, using wchar_t by default).
If you can, use std::wstring to concatenate a L"string" as a drop-in replacement.
A note on MessageBox()
Windows has a funny habit of defining macros for API calls that switch out underlying calls given the program's multibyte configuration. For almost every API call that uses strings, there is a FunctionA and FunctionW call that takes an LPCSTR or LPWCSTR respectively.
MessageBox is one of them. In Visual Studio, you can go into project settings and change your Multi-Byte (wide/narrow) setting or you can simply call MessageBoxA/W directly in order to pass in different encodings of strings.
For example:
LPWCSTR wideString = L"Hello, ";
MessageBoxW(NULL, (std::wstring(wideString) + L"world!").c_str(), L"Hello!", MB_OK);
LPCSTR narrowString = "Hello, ";
MessageBoxA(NULL, (std::string(narrowString) + "world!").c_str(), "Hello!", MB_OK);
If you can change modelPath to std::wstring, it becomes easy:
MessageBox(nullptr, (modelPath + L" not found.").c_str(), nullptr, 0);
I changed your 0 pointer values into nullptr as well.
Since std::string represents a narrow string, std::wstring represents a wide string, and the two are wildly different, casting from one representation to the other does not work, while starting with the appropriate one does. On the other hand, one can properly convert between representations using the new <codecvt> header in C++11.
Related
I need to convert from CString to double in Embedded Visual C++, which supports only old style C++. I am using the following code
CString str = "4.5";
double var = atof( (const char*) (LPCTSTR) str )
and resutlt is var=4.0, so I am loosing decimal digits.
I have made another test
LPCTSTR str = "4.5";
const char* var = (const char*) str
and result again var=4.0
Can anyone help me to get a correct result?
The issue here is, that you are lying to the compiler, and the compiler trusts you. Using Embedded Visual C++ I'm going to assume, that you are targeting Windows CE. Windows CE exposes a Unicode API surface only, so your project is very likely set to use Unicode (UTF-16 LE encoding).
In that case, CString expands to CStringW, which stores code units as wchar_t. When doing (const char*) (LPCTSTR) str you are then casting from a wchar_t const* to a char const*. Given the input, the first byte has the value 52 (the ASCII encoding for the character 4). The second byte has the value 0. That is interpreted as the terminator of the C-style string. In other words, you are passing the string "4" to your call to atof. Naturally, you'll get the value 4.0 as the result.
To fix the code, use something like the following:
CStringW str = L"4.5";
double var = _wtof( str.GetString() );
_wtof is a Microsoft-specific extension to its CRT.
Note two things in particular:
The code uses a CString variant with explicit character encoding (CStringW). Always be explicit about your string types. This helps read your code and catch bugs before they happen (although all those C-style casts in the original code defeats that entirely).
The code calls the CString::GetString member to retrieve a pointer to the immutable buffer. This, too, makes the code easier to read, by not using what looks to be a C-style cast (but is an operator instead).
Also consider defining the _CSTRING_DISABLE_NARROW_WIDE_CONVERSION macro to prevent inadvertent character set conversions from happening (e.g. CString str = "4.5";). This, too, helps you catch bugs early (unless you defeat that with C-style casts as well).
CString is not const char* To convert a TCHAR CString to ASCII, use the CT2A macro - this will also allow you to convert the string to UTF8 (or any other Windows code page):
// Convert using the local code page
CString str(_T("Hello, world!"));
CT2A ascii(str);
TRACE(_T("ASCII: %S\n"), ascii.m_psz);
// Convert to UTF8
CString str(_T("Some Unicode goodness"));
CT2A ascii(str, CP_UTF8);
TRACE(_T("UTF8: %S\n"), ascii.m_psz);
Found a solution using scanf
CString str="4.5"
double var=0.0;
_stscanf( str, _T("%lf"), &var );
This gives a correct result var=4.5
Thanks everyone for comments and help.
I tried to use this code:
USES_CONVERSION;
LPWSTR temp = A2W(selectedFileName);
but when I check the temp variable, just get the first character
thanks in advance
If I recall correctly, CString is typedef'd to either CStringA or CStringW, depending on whether you're building Unicode or not.
LPWSTR is a "Long Pointer to a Wide STRing" -- aka: wchar_t*
If you want to pass a CString to a function that takes LPWSTR, you can do:
some_function(LPWSTR str);
// if building in unicode:
some_function(selectedFileName);
// if building in ansi:
some_function(CA2W(selectedFileName));
// The better way, especially if you're building in both string types:
some_function(CT2W(selectedFileName));
HOWEVER LPWSTR is non-const access to a string. Are you using a function that tries to modify the string? If so, you want to use an actual buffer, not a CString.
Also, when you "check" temp -- what do you mean? did you try cout << temp? Because that won't work (it will display just the first character):
char uses one byte per character. wchar_t uses two bytes per character. For plain english, when you convert it to wide strings, it uses the same bytes as the original string, but each character gets padded with a zero. Since the NULL terminator is also a zero, if you use a poor debugger or cout (which is uses ANSI text), you will only see the first character.
If you want to print a wide string to standard out, use wcout.
In short: You cannot. If you need a non-const pointer to the underlying character buffer of a CString object you need to call GetBuffer.
If you need a const pointer you can simply use static_cast<LPCWSTR>(selectedFilename).
I know this is a decently old question, but I had this same question and none of the previous answers worked for me.
This, however, did work for my unicode build:
LPWSTR temp = (LPWSTR)(LPCWSTR)selectedFileName;
LPWSTR is a "Long Pointer to a Wide String". It is like wchar*.
CString strTmp = "temp";
wchar* szTmp;
szTmp = new WCHAR[wcslen(strTmp) + 1];
wcscpy_s(szTmp, wcslen(strTmp) + 1, strTmp);
I am trying to convert a program for multibyte character to Unicode.
I have gone through the program and preceded the string literals with L so they look like L"string".
This has worked but I am now left with a C style string that won't conform. I have tried the L and putting it in TEXT() but the L gets added to the variable name -- not the string -- if I use TEXT().
I have tried making it a TCHAR but then it complains that it cannot convert a TCHAR to a char *.
What options am I left with?
I know C and C++ are different. It is an old in-house C library that has been used in C++ projects for several years now.
The std::mbstowcs function is what you are looking for:
char text[] = "something";
wchar_t wtext[20];
mbstowcs(wtext, text, strlen(text)+1);//Plus null
LPWSTR ptr = wtext;
for strings,
string text = "something";
wchar_t wtext[20];
mbstowcs(wtext, text.c_str(), text.length());//includes null
LPWSTR ptr = wtext;
--> ED: The "L" prefix only works on string literals, not variables. <--
The clean way to use mbstowcs is to call it twice to find the length of the result:
const char * cs = <your input char*>
size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);
// error if wn == size_t(-1)
wchar_t * buf = new wchar_t[wn + 1](); // value-initialize to 0 (see below)
wn = mbsrtowcs(buf, &cs, wn + 1, NULL);
// error if wn == size_t(-1)
assert(cs == NULL); // successful conversion
// result now in buf, return e.g. as std::wstring
delete[] buf;
Don't forget to call setlocale(LC_CTYPE, ""); at the beginning of your program!
The advantage over the Windows MultiByteToWideChar is that this is entirely standard C, although on Windows you might prefer the Windows API function anyway.
I usually wrap this method, along with the opposite one, in two conversion functions string->wstring and wstring->string. If you also add trivial overloads string->string and wstring->wstring, you can easily write code that compiles with the Winapi TCHAR typedef in any setting.
[Edit:] I added zero-initialization to buf, in case you plan to use the C array directly. I would usually return the result as std::wstring(buf, wn), though, but do beware if you plan on using C-style null-terminated arrays.[/]
In a multithreaded environment you should pass a thread-local conversion state to the function as its final (currently invisible) parameter.
Here is a small rant of mine on this topic.
I'm using the following in VC++ and it works like a charm for me.
CA2CT(charText)
This version, using the Windows API function MultiByteToWideChar(), handles the memory allocation for arbitrarily long input strings.
int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW>0)
{
output = new wchar_t[lenW];
::MultiByteToWideChar(CP_ACP, 0, input, lenA, output, lenW);
}
You may use CString, CStringA, CStringW to do automatic conversions and convert between these types. Further, you may also use CStrBuf, CStrBufA, CStrBufW to get RAII pattern modifiable strings
I want to develop a plugin system using LoadLibrary.
My problem is: I want my function to take a const char* and LoadLibrary takes a LPCTSTR.
I had the bright idea to do (LPCSTR)path which kept giving me a module not found error.
Current code is below. If I uncomment the widepath = L.. line it works fine. I've read solutions using MFC but I'd like to not use MFC.
Current code:
bool PluginLoader::Load(char *path)
{
path = "Release\\ExamplePlugin.dll";
LPCTSTR widepath = (LPCTSTR)path;
//widepath = L"Release\\ExamplePlugin.dll";
HMODULE handle = LoadLibrary(widepath);
if (handle == 0)
{
printf("Path: %s\n",widepath );
printf("Error code: %d\n", GetLastError());
return false;
}
int (*load_callback)() = (int (*)()) GetProcAddress(handle, "_plugin_start#0");
if (load_callback == 0)
{
return false;
}
return load_callback() == LOAD_SUCCESS;
}
Use LoadLibraryA(), it takes a const char*.
Winapi functions that take strings exist in two versions, an A version that takes an Ansi string and a W version that takes a wide string. There's a macro for the function name, like LoadLibrary, that expands to either the A or the W flavor, depending if UNICODE is #defined. You are compiling your program with that #define in effect, so you get LoadLibraryW(). Simply cheat and use LoadLibraryA() explicitly.
I suggest you using TCHAR and LoadLibrary instead of using manually char or wchar_t and LoadLibraryA or LoadLibraryW to make a generic application, both for UNICODE and ASCII characters.
So you could do:
TCHAR x[100] = TEXT("some text");
I suggest you reading this article. LPCTSTR is a const TCHAR*.
Why use LoadLibrary instead of LoadLibraryW or LoadLibraryA? To support both UNICODE and ASCII without creating two different programs, one to work with char and the other with wchar_t.
Also, take a look at what Microsoft says about it: Conventions for Function Prototypes
If you continue to use a char * for the parameter, you'll run into cases where an unusual character is used in the filename and the LoadLibrary will fail. Change the function to use wchar_t instead, and while you're at it make the parameter const since you're not modifying the string.
bool PluginLoader::Load(const wchar_t *path)
I think you'll find that LPCTSTR on 32-bit Windows is a macro that expands to const wchar_t * when the program options are set to Unicode.
The approved method with LoadLibrary is to not use a char const *, but instead use a TCHAR const *, and use the _T macro on all literals:
bool PluginLoader::Load(TCHAR const *path) {
path = _T("Release\\ExamplePlugin.dll");
HMODULE handle = LoadLibrary(path);
if (handle == 0)
{
_tprintf(_T("Path: %s\n"),widepath );
_tprintf(_T("Error code: %d\n"), GetLastError());
return false;
}
int (*load_callback)() = (int (*)()) GetProcAddress(handle, _T("_plugin_start#0"));
if (load_callback == 0)
{
return false;
}
return load_callback() == LOAD_SUCCESS;
}
This will automatically use LoadLibraryW when _UNICODE/UNICODE are defined, and LoadLibraryA when they're not. Likewise, _T will give narrow or wide string literals on the same basis, so it all stays in sync.
I generally prefer to use the W suffixed functions explicitly, and use the L prefix on string literals. Windows works almost exclusively with wide strings internally anyway, so the version A-suffixed versions that take narrow string literals are mostly small stubs that convert their arguments to wide strings, then call the wide string version. Using the wide string version directly saves both time and memory.
Narrow string support in Windows was originally there primarily for compatibility with the long-since defunct Windows 95/98/SE/Me line that lacked wide string support. Those have been gone for quite a while, so about the only reason to use narrow literals now is because that's what you're being supplied from some outside source.
Im creating a DLL that shares memory between different applications.
The code that creates the shared memory looks like this:
#define NAME_SIZE 4
HANDLE hSharedFile;
create(char[NAME_SIZE] name)
{
hSharedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, (LPCSTR)name);
(...) //Other stuff that maps the view of the file etc.
}
It does not work. However if I replace name with a string it works:
SharedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, (LPCSTR)"MY_TEST_NAME");
How can I get this to work with the char array?
I have a java background where you would just use string all the time, what is a LPCSTR? And does this relate to whether my MS VC++ project is using Unicode or Multi-Byte character set
I suppose you should increase NAME_SIZE value.
Do not forget that array must be at least number of chars + 1 to hold \0 char at the end, which shows the end of the line.
LPCSTR is a pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters and defined as follows:
LPCSTR defined as typedef __nullterminated CONST CHAR *LPCSTR;
For example even if you have "Hello world" constant and it has 11 characters it will take 12 bytes in the memory.
If you are passing a string constant as an array you must add '\0' to the end like {'T','E','S','T', '\0'}
If you look at the documentation, you'll find that most Win32 functions take an LPCTSTR, which represents a string of TCHAR. Depending on whether you use Unicode (the default) or ANSI, TCHAR will expand to either wchar_t or char. Also, LPCWSTR and LPCSTR explicitly represent Unicode and ANSI strings respectively.
When you're developing for Win32, in most cases, it's best to follow suit and use LPCTSTR wherever you need strings, instead of explicit char arrays/pointers. Also, use the TEXT("...") macro to create the correct kind of string literals instead of just "...".
In your case though, I doubt this is causing a problem, since both your examples use only LPCSTR. You have also defined NAME_SIZE to be 4, could it be that your array is too small to hold the string you want?