Моя ситуация такова: у меня есть файл .dll и заголовок .h с чисто виртуальным объявлением class MainWindow
. В заголовочном файле есть два определения типов:
typedef MainWindow* (*CREATE_INTERFACE)();
typedef void (*DELETE_INTERFACE)(MainWindow* Window);
, которые позволяют мне создавать и удалять объекты того же типа, что и виртуальный класс.
Я бы хотел, чтобы поддержка загрузки для эту динамическую c библиотеку, которая будет определена в моем классе, назовем ее class Loader
. Мне бы хотелось, чтобы один из моих учеников был умным указателем, определяемым следующим образом:
std::unique_ptr <MainWindow,DELETE_INTERFACE> UI_Driver;
Упрощенный код ниже (без обработки ошибок):
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();
}
};
Код компилируется правильно, загрузка функций из библиотеки .dll также успешна. MainWindow
, определенный в заголовке, имеет метод Show()
, который dr aws пользовательский интерфейс. Если я попытаюсь вызвать его, как описано выше, с помощью метода ShowWindow()
из моего class Loader
, окно не появится.
int main()
{
Loader MyLoader;
MyLoader.ShowWindow(); // <- window does not appear, program crashes
}
НО появляется, если я вызываю этот метод сразу после создания указателя в методе LoadExternalLibrary()
, как показано ниже:
, поэтому вместо:
return std::unique_ptr<Eol_MainWindow_Driver_Generic,DELETE_INTERFACE>(FactoryFunction(),CustomDeleterFunction);
i можно написать:
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
Что происходит? Почему созданный unique_ptr с пользовательским средством удаления перестает работать после копирования?
EDIT : я нашел ответ частично -
FactoryFunction
и CustomDeleterFunction
работают только в функции LoadExternalDll
прицелы. Понятия не имею почему.