C string through dll boundaries

2019-09-03 11:40发布

问题:

We need to return a C string through dll boundaries in a safe way! How can we do this?

My idea:

extern "C" __declspec(dllexport) const char *const Api
{
    ...
    static const char *output = result.c_str();
    return output;
}

回答1:

A pointer is being returned in your example code, but the memory region it is pointing to is probably not staying resident.

If the result variable (std::string?) is on the stack, it's going to be destroyed when the function returns and the returned pointer will be dangling -- certainly not what you want.

A safe way to do this is to strdup() the response, but then the caller will be responsible for freeing the C string. Unloading the DLL means that the returned pointer will be dangling unless it's pointing to a heap variable.



回答2:

The simplest safe way is

extern "C"
__declspec(dllexport) 
size_t Api
    (char* dest,
     size_t dest_size)
{
  if (dest) 
    strncpy(dest, str, dest_size);
  return strlen(str);
}

The other safe way is

extern "C"
__declspec(dllexport) 
void Api
    (void (*callback)(const char*))
{
   callback(str);
}

Returning malloc'd/new'd memory is not 100% safe, because the DLL and the main program can link to different runtimes and use different heaps. If this is the case, the caller can only free/delete the memory by calling free/delete in the DLL (and the DLL must wrap those and export the wrappers). This is a hassle.

Returning static memory is not 100% safe, because the caller might store the pointer and unload the DLL, in which case the pointer will dangle.

Returning automatic memory is of course 100% unsafe.