I suppose you want to mix creation and destruction of the objects (Config
and the shared_ptr
). If the DLL client is not compiled with the same version and configuration of the compiler you would be in troubles (for example, mixing debug and release modules). The main problem I see here: there is not any type of standard ABI for C++.
I was thinking by creating the share_ptr at the dll headers (getNewNode) it would prevent mixed implementations of std::shared_ptr ...but I don't know if that is a good idea?
If you define your header file to create the shared_ptr, that would be OK if only a module use that header file. I mean, if the shared_ptr is not to be used for the content of the DLL, for example. BUT if other client module (a binary module, like other DLL) use also that header, you must be sure they are compiled with the same compiler and compiling configuration. If you have not that guarantee, then is not good idea.
But I also construct the new object inside the DLL (_constructNewNode) and this means it should also be destructed there?
If you construct the object inside the DLL, you'll be better destroying inside the DLL. How to do that? specifying a deleter at shared_ptr
construction. Something like
struct ConfigDeleter {
void operator()(Config* c) {
c->destroy(); // or as you want to implement it.
};
typedef std::shared_ptr<Config, ConfigDeleter> ConfigPtr;
I tried to construct it in the headers and so in the user code scope (getNewNodeFromHeader)... this shouldn't cause problems?
As before, it depends if you can guarantee all modules are homogeneous (same compiler version and configuration, library, etc.). But of you want to implement as that, do it well:
// construct obj and shared_ptr in header
auto obj_ = make_shared<Config>();
obj_->init(query);
It is exception-safe and more efficient: just one allocation to store the object and the reference, instead two allocations in your sample.
If you want your code be safe for mixing modules, implement all allocations (shared_ptr
included) into the DLL, if they are shared. Exports a "C" interface, and create header file to wrap that interface in classes. Something like:
class WConfig {
public:
WConfig(): m(IDll->create()) {
}
// other member functions as interface stub
~WConfig() {
IDll->release(m);
}
private:
Config* m;
};
To share this object, you can use copy constructor (that copy the pointer and call to IDll->reference(m), for example) or any other approach.