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?
Related
TCHAR path[_MAX_PATH+1];
std::wstring ws(&path[0], sizeof(path)/sizeof(path[0]));
or
TCHAR path[_MAX_PATH];
std::wstring ws(&path[0]);
While converting a TCHAR to wstring both are correct?
I'm asking just for clarification, I'm in doubt if I'm converting it correctly.
The code is problematic in several ways.
First, std::wstring is a string of wchar_t (aka WCHAR) while TCHAR may be either CHAR or WCHAR, depending on configuration. So either use WCHAR and std::wstring, or TCHAR and std::basic_string<TCHAR> (remembering that std::wstring is just a typedef for std::basic_string<WCHAR>).
Second, the problem is with string length. This snippet:
WCHAR path[_MAX_PATH];
std::wstring ws(&path[0], sizeof(path)/sizeof(path[0]));
will create a string of length exactly _MAX_PATH + 1, plus a terminating null (and likely with embedded nulls, C++ strings allow that). Likely not what you want.
The other one:
WCHAR path[_MAX_PATH+1];
...
std::wstring ws(&path[0]);
expects that path holds a null-terminated string by the time ws is constructed, and copies it into ws. If path happens to be not null-terminated, UB ensues (usually, either garbage in ws or access violation).
If your path is either null-terminated or contains _MAX_PATH-length string, I suggest using it like this:
WCHAR path[_MAX_PATH+1];
... // fill up to _MAX_PATH characters
path[_MAX_PATH] = L'0'; // ensure it is null-terminated
std::wstring ws(path); // construct from a null-terminated string
Or if you know the actual length, just pass it:
WCHAR path[_MAX_PATH];
size_t length = fill_that_path(path);
std::wstring ws(path, length); // length shouldn’t include the null terminator, if any
See the docs (it’s the same for string and wstring except of different char type).
It depends on the content of path. If it is an arbitrary char array that can contain null characters, then you should use the first version which explicitely gives the size. But if is contains a null terminated string (and only contains unused values after the first null), then you should use the second one which will stop on the terminating null character.
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.
I am new to MFC. I am trying to do simple mfc application and I'm getting confuse in some places. For example, SetWindowText have two api, SetWindowTextA, SetWindowTextW one api takes char * and another one accepts wchar_t *.
What is the use of char * and wchar_t *?
char is used for so called ANSI family of functions (typically function name ends with A), or more commonly known as using ASCII character set.
wchar_t is used for new so called Unicode (or Wide) family of functions (typically function name ends with W), which use UTF-16 character set. It is very similar to UCS-2, but not quite it. If character requires more than 2 bytes, it will be converted into 2 composite codepoints, and this can be very confusing.
If you want to convert one to another, it is not really simple task. You will need to use something like MultiByteToWideChar, which requires knowing and providing code page for input ANSI string.
On Windows, APIs that take char * use the current code page whereas wchar_t * APIs use UTF-16. As a result, you should always use wchar_t on Windows. A recommended way to do this is to:
// Be sure to define this BEFORE including <windows.h>
#define UNICODE 1
#include <windows.h>
When UNICODE is defined, APIs like SetWindowText will be aliased to SetWindowTextW and can therefore be used safely. Without UNICODE, SetWindowText will be aliased to SetWindowTextA and therefore cannot be used without first converting to the current code page.
However, there's no good reason to use wchar_t when you are not calling Windows APIs, since its portable functionality is not useful, and its useful functionality is not portable (wchar_t is UTF-16 only on Windows, on most other platforms it is UTF-32, what a total mess.)
SetWindowTextA takes char*, which is a pointer to ANSI strings.
SetWindowTextW takes wchar_t*, which is a pointer to "wide" strings (Unicode).
SetWindowText has been defined (#define) to either of these in header Windows.h based on the type of application you are building. If you are building a UNICODE build then your code will automatically use SetWindowTextW.
SetWindowTextA is there primarily to support legacy code, which needs to be built as SBCS (Single byte character set).
char* : It means that this is a pointer to data of type char.
Example
// Regular char
char aChar = 'a';
// Pointer to char
char* aPointer = new char;
*aPointer = 'a';
// Pointer to an array of 10 chars
char* anArray = new char[ 10 ];
*anArray = 'a';
anArray[ 1 ] = 'b';
// Also a pointer to an array of 10
char[] anArray = new char[ 10 ];
*anArray = 'a';
anArray[ 1 ] = 'b';
wchar_t* : wchar_t is defined such that any locale's char encoding can be converted to a wchar_t representation where every wchar_t represents exactly one codepoint.
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 have a TCHAR and value as below:
TCHAR szDestPathRoot[MAX_PATH]="String This";
Now I want the 1st three character from TCHAR , like below:
szDestPathRoot.substring(0,2);
How can I do this.
TCHAR[] is a simple null-terminated array (rather than a C++ class). As a result, there's no ".substring()" method.
TCHAR[] (by definition) can either be a wide character string (Unicode) or a simple char string (ASCII). This means there are wcs and str equivalents for each string function (wcslen() vs strlen(), etc etc). And an agnostic, compile-time TCHAR equivalent that can be either/or.
The TCHAR equivalent of strncpy() is tcsncpy().
Final caveat: to declare a TCHARliteral, it's best to use the _T() macro, as shown in the following snippet:
TCHAR szDestPathRoot[MAX_PATH] = _T("String This");
TCHAR szStrNew[4];
_tcsncpy (str_new, szTestPathRoot, 3);
You may find these links to be of interest:
http://msdn.microsoft.com/en-us/library/xdsywd25%28VS.71%29.aspx
http://www.i18nguy.com/unicode/c-unicode.html
http://msdn.microsoft.com/en-us/library/5dae5d43(VS.80).aspx (for using the secure _tcsncpy_s)
TCHAR szDestPathRoot[MAX_PATH]="String This";
TCHAR substringValue[4] = {0};
memcpy(substringValue, szDestPathRoot, sizeof(TCHAR) * 3);
As you have tagged your question with "C++" you can use the string classes of the std library:
std::wstring strDestPathRoot( _T("String This") );
strDestPathRoot.substr( 0, 2 );
This is somewhat ugly but if you know for sure that:
The string holds at least 4 TCHAR (3 chars plus the terminating NUL)
The content of the string can be modified (which is the case in your example).
You don't have to keep the original string intact
You could just put a terminating NUL at the 4th position to make the string 3 char long.
szDestPathRoot[3] = _T('\0');
Note that this operation is destructive to the original string
You should really be using a string class in C++ code though.