形勢被稱爲
外部庫(LibraryExternal),我不能改變LibraryA的調用LoadLibrary。在它成功加載後,它會調用一個導出的函數AExport,它返回一個指向ClassA的指針,該指針是一個靜態實例。在AExport返回之前,它也通過稱爲LibraryB的LoadLibrary加載一個庫。在成功加載後,它調用一個導出的函數BExport,該函數繼而返回一個指向靜態實例ClassB的指針。
重要
LibraryA的是一個C++ DLL與vs2012 XP工具編譯和LibraryB是一個C++/CLI DLL也與vs2012 XP工具編譯。
爲了理解AExport和BExport返回的指針,所有庫都共享一些只定義ClassA和ClassB需要派生的庫。它們只不過是存根(stub)而已,在這個問題中並不重要(只有純虛函數,沒有字段,ctor/dtor也沒有做任何事情)。
結果
當LibraryExternal被通過程序退出卸載,它調用LibraryA的FreeLibrary則。這成功地調用ClassA的析構函數,然後釋放庫LibraryB。但是ClassB的析構函數絕不會以某種方式運行。
所需的結果
有無ClassB的析構函數運行
ClassA.h
#include <StubA.h>
class StubB;
class ClassA: public StubA
{
public:
ClassA();
~ClassA();
bool Initialize();
static ClassA &GetInstance()
{
static ClassA INSTANCE;
return INSTANCE;
}
private:
ClassA(ClassA const &);
void operator=(ClassA const&);
HMODULE wrapperModule;
StubB *wrapperPlugin;
};
ClassA.cpp
#include "ClassA.h"
#include <Windows.h>
// typedef WrapperPlugin *(*WrapperPluginInitType)(); This is normally in shared library
static const wchar_t *WRAPPER_MODULE_NAME = L"LibraryB.dll";
static const char *WRAPPER_MODULE_INIT_FUNCTION_NAME = "BExport";
ClassA::ClassA() :
wrapperModule(NULL),
wrapperPlugin(NULL)
{
}
ClassA::~ClassA()
{
if (this->wrapperModule != NULL)
{
FreeLibrary(this->wrapperModule);
}
}
bool CSharpBridge::Initialize()
{
this->wrapperModule = LoadLibraryW(WRAPPER_MODULE_NAME);
if (this->wrapperModule == NULL)
{
return false;
}
WrapperPluginInitType wrapperPluginInit = reinterpret_cast<WrapperPluginInitType>(GetProcAddress(this->wrapperModule, WRAPPER_MODULE_INIT_FUNCTION_NAME));
if (wrapperPluginInit == NULL)
{
return false;
}
this->wrapperPlugin = wrapperPluginInit();
if (this->wrapperPlugin == NULL)
{
return false;
}
return true;
}
extern "C"
{
__declspec(ddlexport) StubA *AExport()
{
if (!ClassA::GetInstance().Initialize())
{
return NULL;
}
return &ClassA::GetInstance();
}
}
ClassB.h
#include <StubB.h>
class ClassB : public StubB
{
public:
ClassB();
~ClassB();
static ClassB &GetInstance()
{
static ClassB INSTANCE;
return INSTANCE;
}
private:
ClassB (ClassB const &);
void operator=(ClassB const&);
};
ClassB.cpp
#include "ClassB.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
ClassB::ClassB()
{
std::ofstream myfile;
myfile.open("C:\\Users\\USERNAME\\Desktop\\test1.txt");
myfile << "ClassB::ClassB\r\n";
myfile.close();
}
ClassB::~ClassB()
{
std::ofstream myfile;
myfile.open("C:\\Users\\USERNAME\\Desktop\\test3.txt");
myfile << "ClassB::~ClassB\r\n";
myfile.close();
}
extern "C"
{
__declspec(dllexport) StubB *WrapperInit()
{
std::ofstream myfile;
myfile.open("C:\\Users\\USERNAME\\Desktop\\test2.txt");
myfile << "WrapperInit\r\n";
myfile.close();
return &ClassB::GetInstance();
}
}
現在我知道100%的把握認爲ClassA的構造函數/析構函數調用,由於一些LibraryExternal功能,這給我一些文本確認。我似乎得到了生成test1.txt和test2.txt。但不是test3.txt。
在此之後,我仍然需要創建一個託管的引用LibraryC這是一個C#DLL和'破壞',當ClassB被破壞。
至少解釋你爲什麼downvoted所以我可以做得更好下一次.. – Neijwiert
嗯,我可以看到如何發生。當你要求志願者投入他們的空閒時間來幫助你時,最起碼的禮貌是發佈可以編譯和運行的代碼來重現問題。此代碼不會編譯,也不會運行。相當簡單的照顧,只是先編譯和運行它自己。 –