I wrote a managed C++ class that has the following function:
void EndPointsMappingWrapper::GetLastError(char* strErrorMessage)
{
strErrorMessage = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer();
}
As you can see, this is a simple method to copy the managed string of the last error to the unmanaged world (char*
).
From my unmanaged class I call the method like this:
char err[1000];
ofer->GetLastError(err);
Putting a breakpoint at the managed C++ method shows that the string is successfully translated into the char*
. However, once I return to the unmanaged class, the content of err[1000]
is lost and it's empty again.
You are assigning the value of the passed parameter (strErrorMessage) instead of copying to that address the content of the buffer returned by Marshal::StringToHGlobalAnsi.
A correct implementation should be:
void EndPointsMappingWrapper::GetLastError(char* strErrorMessage, int len)
{ char *str = (char*) Marshal::StringToHGlobalAnsi(_managedObject->GetLastError()).ToPointer();
strncpy(strErrorMessage,str,len);
strErrorMessage[len-1] = '\0';
Marshal::FreeHGlobal(IntPtr(str));
}
The length is the size of the buffer passed.
strncpy()
will copy at the most len bytes. If there is no null byte among the first n bytes of the str, the destination string won't be null terminated. For that reason we force the '\0' in the last byte of the buffer.