Search code examples
.netc++managed-c++

string to char* marshaling


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.


Solution

  • 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.