cannot convert from 'std::string' to 'LPSTR' - c++

As I clould not pass LPCSTR from one function to another (Data get changed) I tried passing it as a string.
But later I need to again convert it back to LPSTR. While trying the conversion I am getting the above error:
cannot convert from 'std::string' to 'LPSTR'
How can I resolve this?

That's just because you should use std::string::c_str() method.
But this involves const_cast in given case because const char * returned by c_str() can not be assigned to a non-constant LPSTR.
std::string str = "something";
LPSTR s = const_cast<char *>(str.c_str());
But you must be sure that lifetime of str will be longer that that of LPTSTR variable.
Another mention, if code compiles as Unicode-conformant, then types LPTSTR and std::string are incompatible. You should use std::wstring instead.
Important note: If you pass the resulting pointer s from above to a function which tries to modify the data it is pointing to this will result in undefined behaviour. The only way to properly deal with it is to duplicate the string into a non-const buffer (e.g. via strdup)

If you need an LPSTR, that means the string will/may be modified. std::string::c_str() returns a const pointer, and you can't just const_cast it away and hope all is good in the world, because it isn't. The string may be changed in all sorts of nasty ways, and your original std::string will be oblivious to all of them.
Try this instead:
// myFunction takes an LPSTR
std::string cppString = "something";
LPSTR cString = strdup( cppString.c_str() );
try {
myFunction( cString );
cppString = cString;
} catch(...) {
free( cString );
}
Wrap the string in a smart pointer and get rid of the try...catch for bonus points (don't forget the custom deleter).

There is a function on std::string c_str() . However I doubt that you could not use a std::string in your case.

Are you running somestringvariablename.c_str()?
That should work.

An LPSTR can be substituted with by using a TCHAR (i.e. found in tchar.h). So if you have a std::string, you can use the method std::string::c_str().

If the function, you are calling does not write to string, but only reads it, then you can simply use string::c_str method. If it is going to write something, then you probably should ensure that your string has enough space by calling string::reserve().

Related

Can't assign named pipe name to LPTSTR variable

I'm getting used to win32 API shenanigans but it's tiresome, the problem I face this time regards the assignemt of a name of a named pipe, this is what I'm doing:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
This is verbatim from MSDN webpages, and surprise, surprise, this doesn't compile and issues the following error:
E0144 a value of type "const wchar_t *" cannot be used to initialize an entity of type "LPTSTR"
Now a cast will solve the assignment but then I get a 109 error, which is, you guessed it, ERROR_BROKEN_PIPE.
How should I solve this?
The problem is that, despite claims to the contrary, the examples given in the WinAPI documentation are written in (mostly) C, not C++. Also, the use of string literals to initialize non-const character pointers is no longer allowed in C++ (since C++11).
So, replace:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
with:
TCHAR lpszPipename[] = TEXT("\\\\.\\pipe\\mynamedpipe");
(Whether or not that will fix your ERROR_BROKEN_PIPE is another matter, though!)
LPTSTR is the non-const version. You're trying to acquire a non-const pointer to a string literal.
This used to be valid C++ (it still is valid C, hence the sample), but it was very dangerous, so they made illegal in C++11. You either want:
wchar_t const* lpszPipename = L"\\\\.\\pipe\\mynamedpipe";
or
wchar_t pipename[] = L"\\\\.\\pipe\\mynamedpipe";
CreateNamedPipe take pointer to constant string ( LPCSTR or LPCWSTR) in place pipe name. so and do direct
CreateNamedPipe(TEXT("\\\\.\\pipe\\mynamedpipe"), ..)
i not view any reason for
LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
CreateNamedPipe(lpszPipename , ..)
however if by some reason use lpszPipename - it must be declared as pointer to constant string. LPCTSTR lpszPipename instead LPTSTR lpszPipename
possible and next solution - declare in global scope
static const WCHAR gPipename[] = L"\\\\.\\pipe\\mynamedpipe";
and use it, on binary level CreateNamedPipeW(L"\\\\.\\pipe\\mynamedpipe"), ..) and CreateNamedPipeW(gPipename, ..) produce the same code

Converting std::string to LPCSTR [duplicate]

As I clould not pass LPCSTR from one function to another (Data get changed) I tried passing it as a string.
But later I need to again convert it back to LPSTR. While trying the conversion I am getting the above error:
cannot convert from 'std::string' to 'LPSTR'
How can I resolve this?
That's just because you should use std::string::c_str() method.
But this involves const_cast in given case because const char * returned by c_str() can not be assigned to a non-constant LPSTR.
std::string str = "something";
LPSTR s = const_cast<char *>(str.c_str());
But you must be sure that lifetime of str will be longer that that of LPTSTR variable.
Another mention, if code compiles as Unicode-conformant, then types LPTSTR and std::string are incompatible. You should use std::wstring instead.
Important note: If you pass the resulting pointer s from above to a function which tries to modify the data it is pointing to this will result in undefined behaviour. The only way to properly deal with it is to duplicate the string into a non-const buffer (e.g. via strdup)
If you need an LPSTR, that means the string will/may be modified. std::string::c_str() returns a const pointer, and you can't just const_cast it away and hope all is good in the world, because it isn't. The string may be changed in all sorts of nasty ways, and your original std::string will be oblivious to all of them.
Try this instead:
// myFunction takes an LPSTR
std::string cppString = "something";
LPSTR cString = strdup( cppString.c_str() );
try {
myFunction( cString );
cppString = cString;
} catch(...) {
free( cString );
}
Wrap the string in a smart pointer and get rid of the try...catch for bonus points (don't forget the custom deleter).
There is a function on std::string c_str() . However I doubt that you could not use a std::string in your case.
Are you running somestringvariablename.c_str()?
That should work.
An LPSTR can be substituted with by using a TCHAR (i.e. found in tchar.h). So if you have a std::string, you can use the method std::string::c_str().
If the function, you are calling does not write to string, but only reads it, then you can simply use string::c_str method. If it is going to write something, then you probably should ensure that your string has enough space by calling string::reserve().

Convert std::string to char * alternative

I have done a search in google and been told this is impossible as I can only get a static char * from a string, so I am looking for an alternative.
Here is the situation:
I have a .txt file that contains a list of other .txt files and some numbers, this is done so the program can be added to without recompilation. I use an ifstream to read the filenames into a string.
The function that they are required for is expecting a char * not a string and apparently this conversion is impossible.
I have access to this function but it calls another function with the char * so I think im stuck using a char *.
Does anyone know of a work around or another way of doing this?
In C++, I’d always do the following if a non-const char* is needed:
std::vector<char> buffer(str.length() + 1, '\0');
std::copy(str.begin(), str.end(), buffer.begin());
char* cstr = &buffer[0];
The first line creates a modifiable copy of our string that is guaranteed to reside in a contiguous memory block. The second line gets a pointer to the beginning of this buffer. Notice that the vector is one element bigger than the string to accomodate a null termination.
You can get a const char* to the string using c_str:
std::string str = "foo bar" ;
const char *ptr = str.c_str() ;
If you need just a char* you have to make a copy, e.g. doing:
char *cpy = new char[str.size()+1] ;
strcpy(cpy, str.c_str());
As previous posters have mentioned if the called function does in fact modify the string then you will need to copy it. However for future reference if you are simply dealing with an old c-style function that takes a char* but doesn't actually modfiy the argument, you can const-cast the result of the c_str() call.
void oldFn(char *c) { // doesn't modify c }
std::string tStr("asdf");
oldFn(const_cast< char* >(tStr.c_str());
There is c_str(); if you need a C compatible version of a std::string. See http://www.cppreference.com/wiki/string/basic_string/c_str
It's not static though but const. If your other function requires char* (without const) you can either cast away the constness (WARNING! Make sure the function doesn't modify the string) or create a local copy as codebolt suggested. Don't forget to delete the copy afterwards!
Can't you just pass the string as such to your function that takes a char*:
func(&string[0]);

How to create a CString from an array of chars?

Need to log the content of buf using the LogMethod() below the problem is that
LogMethos only accepts a "Const CString&"
char buf[1024];
strcpy(buf, cErrorMsg);
// need to pass to LogMethod "buf" how do i do that?
log.LogMethod(const CString &);
Thans
Rev
Reversed
If you're talking about MFC CString, as far as I can tell, it should have a non-explicit constructor taking TCHAR const *. In other words, the following should work.
log.LogMethod(buf);
If it doesn't, please post the error message.
log.LogMethod(CString(buf));
This will avoid the problem where the compiler won't automatically create the CString object using the appropriate constructor since the argument is a reference (It would have if the argument was a "plain" CString).
CString cs;
cs = buf;
log.LogMethod(cs)

Pass an element from C type string array to a COM object as BSTR? (in C++)

I am writing a C++ DLL that is called by an external program.
1.) I take an array of strings (as char *var) as an argument from this program.
2.) I want to iterate through this array and call a COM function on each element of the string array. The COM function must take a BSTR:
DLL_EXPORT(void) runUnitModel(char *rateMaterialTypeNames) {
HRESULT hr = CoInitialize(NULL);
// Create the interface pointer.
IUnitModelPtr pIUnit(__uuidof(BlastFurnaceUnitModel));
pIUnit->initialiseUnitModel();
int i;
for(i=0; i < sizeOfPortRatesArray; i++)
pIUnit->createPort(SysAllocString(BSTR((const char *)rateMaterialTypeNames[i])));
I think its the SysAllocString(BSTR((const char *)rateMaterialTypeNames[i])) bit that is giving me problems. I get an access violation when the programs runs.
Is this the right way to access the value of the rateMaterialTypeName at i? Note I am expecting something like "IronOre" as the value at i, not a single character.
If you're using Microsofts ATL, you can use the CComBSTR class.
It will accept a char* and create a BSTR from it, also, you don't need to worry about deleting the BSTR, all that happens in the dtor for CComBSTR.
Also, see Matthew Xaviers answer, it doesn't look like you're passing your array of strings into that function properly.
Hope this helps
Because a variable holding a C string is just a pointer to the first element (a char*), in order to pass an array of C strings, the parameter to your function should be a char**:
DLL_EXPORT(void) runUnitModel(char **rateMaterialTypeNames)
This way, when you evaluate rateMaterialTypeNames[i], the result will be a char*, which is the parameter type you need to pass to SysAllocString().
Added note: you will also need to convert the strings to wide chars at some point, as Tommy Hui's answer points out.
If the parameter to the function rateMaterialTypeNames is a string, then
rateMaterialTypeNames[i]
is a character and not a string. You should use just the parameter name itself.
In addition, casts in general are bad. The conversion to a BSTR is a big flag. The parameter type for SysAllocString is
const OLECHAR*
which for 32-bit compilers is a wide character. So this will definitely fail because the actual parameter is a char*.
What the code needs is a conversion of narrow string to a wide string.
const OLECHAR* pOleChar = A2COLE( *pChar );
BSTR str = SysAllocString( pOleChar );
// do something with the 'str'
SysFreeString( str ); // need to cleanup the allocated BSTR