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
.
std:string
or a CString
to a DLL
? struct
with std::string members
and fill it in a DLL
?DLL
return a pointer to a struct allocated there? Will it be valid? Can I delete it after?std::String
or a Cstring
?Thanks !
It is part of STL indeed. And std::string is just basic_string<char> typedef. It is container, specialized (not in C++ "specialization" meaning :) ) for data storage with string semantics.
Yes, std::string (since C++11) is able to be moved i.e. it supports move semantics.
There is no functionality difference between string and std::string because they're the same type. That said, there are times where you would prefer std::string over string .
The std::string class manages the underlying storage for you, storing your strings in a contiguous manner. You can get access to this underlying buffer using the c_str() member function, which will return a pointer to null-terminated char array.
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
or CString
). 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With