Charles Ray
Charles Ray

Reputation: 480

Converting from LPCWSTR to LPCSTR

I'm having trouble trying to cast a LPCWSTR to an LPCSTR.

Some Background

I am programming a VC++ 2010 application, and have already run into the situation where I had to convert from type System::String^ to std::string. I used this code to do so:

private: std::string toss(System::String^ s)
    {
        msclr::interop::marshal_context context;
        return context.marshal_as<std::string>(s);
    }

Doing so, I thought I would solve all my problems. I was wrong. From this, I need to cast a std::string as an LPCSTR, to use with some Windows API.

After reading some of the existing questions on SO, I feel like I am stuck. I was told to use:

LPCSTR str = existingstr.c_str();

When I use this, however, I am given the error: Cannot convert from LPCWSTR to LPCSTR

Does anyone have a better idea of what I should do in this specific case, or how I can convert from LPCWSTR to LPCSTR?

Thanks in advance.

Upvotes: 2

Views: 17881

Answers (4)

Inverse
Inverse

Reputation: 4476

It looks like you're using MFC based on the LPCSTR keyword. MFC provides a couple conversion macro/functions:

http://msdn.microsoft.com/en-us/library/87zae4a3%28v=vs.80%29.aspx

CA2W(s): converts an ascii string to wide string, e.g. CStringA -> CStringW

CW2A(s): converts an wide string to ascii string, e.g. CStringW -> CStringA

and there are others.

Upvotes: 1

sean e
sean e

Reputation: 11935

Given that existingstr.c_str() is causing the Cannot convert from LPCWSTR to LPCSTR you must be compiling with UNICODE defined. Use LPCWSTR instead of LPCSTR for the param that you'll pass to the Win API:

LPCWSTR str = existingstr.c_str();

At any rate, CString has some nice conversion ctors:

CStringA strA(existingstr.c_str());

You can pass strA to anything that wants an LPCSTR.

Upvotes: 2

AJ S.
AJ S.

Reputation: 400

I use the following two routines when converting back and forth between wchar and char-based strings:

include <string>      // std::string, std::wstring
include <algorithm>   // std::copy  

std::wstring StringToWString(const std::string& s)  
{  
    std::wstring temp(s.length(),L' ');  
    std::copy(s.begin(), s.end(), temp.begin());  
    return temp;  
}  


std::string WStringToString(const std::wstring& s)  
{  
    std::string temp(s.length(), ' ');  
    std::copy(s.begin(), s.end(), temp.begin());  
    return temp;  
}  

You can now solve your problem by the following assuming 'existingstr' is a wide-char string:

std::string narrow_str(WStringToString(existingstr));  

LPCSTR win_str = narrow_str.c_str();  

You can go the other way just as easily given some 'narrowstr':

std::wstring wide_str(StringToWString(narrowstr));  

LPWCSTR win_wstr = wide_str.c_str();  

Clearly, this is not efficient as you are both allocating a local and then copying it back through the stack (I mitigate that a bit by using the constructor initialization instead of an assignment...some compilers optimize away the extra copy that way).

If possible, it would be better to work with the appropriate version of the Windows API by using the UNICODE macro (see http://msdn.microsoft.com/en-us/library/ff381407%28v=vs.85%29.aspx - Working With Strings (Windows)).

However, assuming that is not possible for compatibility reasons, it does give you some insight as to what needs to happen.

Upvotes: 5

user530189
user530189

Reputation:

Edit: completely misread the question so disregard my earlier answer, sorry. If you need to later pass this string into a Windows API, do you have a reason for using std::string and not std::wstring?

Additional edit: there's some confusion on my part here. What is the type of existingstr and what is the signature of the Windows API function you're calling? I think that would help clear things up. If existingstr is std::string, then .cstr() is compatible with LPCSTR (i.e. char const*). If existingstr is std::wstring, it is not. Is the API taking LPCSTR or LPCWSTR?

You could use this instead:

private: std::wstring toss(System::String^ s)
{
   std::wstring result;
   {
       pin_ptr<wchar_t const> ptr = PtrToStringChars(s);
       result = ptr;
   }
   return result;
}

.c_str() on a std::wstring would result in a wchar_t const* (i.e. a LPCWSTR).

Upvotes: 2

Related Questions