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;
}
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;
}
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.
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.