My situation is as follows:
I have a .dll file and a .h header with a purely virtual class MainWindow
declaration. There are two type definitions in the header file:
typedef MainWindow* (*CREATE_INTERFACE)();
typedef void (*DELETE_INTERFACE)(MainWindow* Window);
which allow me to create and delete an object of the same type as a virtual class.
I would like that loading support for this dynamic library to be defined in my class, let's call it class Loader
. I would like one of my class members to be a smart pointer defined as follows:
std::unique_ptr <MainWindow,DELETE_INTERFACE> UI_Driver;
The simplified code below (without error handling):
class Loader
{
private:
HINSTANCE DllHandle;
CREATE_INTERFACE FactoryFunction;
DELETE_INTERFACE CustomDeleterFunction;
std::unique_ptr<MainWindow,DELETE_INTERFACE> UI_Driver;
std::unique_ptr<MainWindow,DELETE_INTERFACE> LoadExternalLibrary()
{
std::wstring WideFileName=L"MainWindow.dll";
std::string FileName(std::begin(WideFileName),std::end(WideFileName));
this->DllHandle=::LoadLibrary(WideFileName.c_str());
// Get the function from the DLL
FactoryFunction=reinterpret_cast<CREATE_INTERFACE>(::GetProcAddress(DllHandle,"Create"));
CustomDeleterFunction=(DELETE_INTERFACE)GetProcAddress(DllHandle,"Delete");
return std::unique_ptr<MainWindow,DELETE_INTERFACE>(FactoryFunction(),CustomDeleterFunction);
};
public:
UI_Service() : UI_Driver(LoadExternalLibrary())
{
}
~UI_Service()
{
if(UI_Driver)
::FreeLibrary(this->DllHandle);
}
void ShowWindow()
{
UI_Driver->Show();
}
};
The code compiles correctly, loading functions from the .dll library is also succesfull. A MainWindow
defined in header has a Show()
method that draws the user interface. If I try to call it like above with the ShowWindow()
method from my class Loader
, the window does not appear.
int main()
{
Loader MyLoader;
MyLoader.ShowWindow(); // <- window does not appear, program crashes
}
BUT it appears if I call this method immediately after creating the pointer in the LoadExternalLibrary()
method as below:
so instead:
return std::unique_ptr<Eol_MainWindow_Driver_Generic,DELETE_INTERFACE>(FactoryFunction(),CustomDeleterFunction);
i can write:
std::unique_ptr<Eol_MainWindow_Driver_Generic,DELETE_INTERFACE> UI(FactoryFunction(),CustomDeleterFunction);
UI->Show(); // <- Window appears
return UI; // <- It will never happen because the Show() is blocking the thread
What is going on? Why does the created unique_ptr with custom deleter stop working after copying?
EDIT: I found the answer partially -
FactoryFunction
and CustomDeleterFunction
only work in LoadExternalDll
function scopes. I have no idea why.