Can I pass std::string to a DLL?
I separated a code fragment into a DLL
because it will be frequently updated and in this way it should be easier to deploy.
But I have questions about what I can do and what I cannot do with a DLL
.
- Can I pass a
std:string
or aCString
to aDLL
? - Can I pass a pointer to a
struct
withstd::string members
and fill it in aDLL
? - Can a
DLL
return a pointer to a struct allocated there? Will it be valid? Can I delete it after? - What should better to pass, a
std::String
or aCstring
?
Thanks !
Solution 1:
You have a choice to make:
Tightly coupled DLL: The DLL is built with the exact same compiler version, packing and calling convention settings, library options as the application, and both dynamically link to the runtime library (
/MD
compiler option). This lets you pass objects back and forth including STL containers, allocate DLL objects from inside the application, derive from base classes in the other module, do just about everything you could without using DLLs. The disadvantage is that you can no longer deploy the DLL independently of the main application. Both must be built together. The DLL is just to improve your process startup time and working set, because the application can start running before loading the DLL (using the/delayload
linker option). Build times are also faster than a single module, especially when whole program optimization is used. But optimization doesn't take place across the application-DLL boundary. And any non-trivial change will still require rebuilding both.Loosely coupled: The application doesn't depend on the class layout of objects defined by the DLL. You use only highly compatible data types: primitive types, pointers, function pointers, and user-defined types made up of these elements. Classes inherit from a base class which defines interface and has no data members and no non-virtual functions (this means no constructors and no sharing of standard library objects such as
std::string
orCString
). All allocation and object creation must be done through a factory function. Memory must be deallocated from the module which allocated it. Code and data are separated. The header file explicitly states the calling convention of each exported function and packing of each structure allowed to cross module boundaries. The advantage is that the DLL and application can be updated completely independently. You can rebuild one with a new runtime library, new compiler version, or even in a completely new language, and don't have to even touch the other.
I always advise using the loosely coupled approach.
Solution 2:
There is a danger when passing anything into and out of a DLL if it's based on a template. Compiler options can affect the layout of the object, and a template class can't be confined to a single compilation unit; some of it will be distributed to the calling module.
In the case of a string, I would pass a const char *
(or const wchar_t *
or const TCHAR *
) and do the conversion to std::string
or CString
on the other side of the interface, within the DLL.