C++ 未调用第二个dll中静态实例的析构函数
形势 无法更改的外部库(LibraryExternal)调用LibraryA上的LoadLibrary。成功加载后,它调用导出的函数AExport,该函数返回指向ClassA的指针,ClassA是一个静态实例。在AExport返回之前,它也通过LoadLibrary(称为LibraryB)加载库。成功加载后,它调用导出的函数BExport,该函数反过来返回指向静态实例ClassB的指针 重要C++ 未调用第二个dll中静态实例的析构函数,c++,c++-cli,C++,C++ Cli,形势 无法更改的外部库(LibraryExternal)调用LibraryA上的LoadLibrary。成功加载后,它调用导出的函数AExport,该函数返回指向ClassA的指针,ClassA是一个静态实例。在AExport返回之前,它也通过LoadLibrary(称为LibraryB)加载库。成功加载后,它调用导出的函数BExport,该函数反过来返回指向静态实例ClassB的指针 重要 Labalya是用VS201XP工具编译的C++ DLL,而LabyAb是用VS201XP工具编译的C
Labalya是用VS201XP工具编译的C++ DLL,而LabyAb是用VS201XP工具编译的C++/CLI DLL。 所有库共享一些其他库,这些库只定义ClassA和ClassB需要从中派生的内容,以便理解AExport和BExport返回的指针。它们只不过是存根,在这个问题上无关紧要(只有纯虚拟函数,没有字段,在ctor/dtor中也没有任何操作)
结果 当LibraryExternal通过程序退出卸载时,它调用LibraryA上的FreeLibrary。这成功地调用了ClassA的析构函数,从而释放了LibraryB库。但是ClassB的析构函数从未以某种方式运行过 期望的结果 运行ClassB析构函数 A.h级#包括
B类;
A类:公共存根
{
公众:
类别a();
~ClassA();
bool初始化();
静态ClassA&GetInstance()
{
静态ClassA实例;
返回实例;
}
私人:
ClassA(ClassA常数&);
void运算符=(ClassA常量&);
模块包装器模块;
StubB*包装插件;
};
ClassA.cpp
#包括“ClassA.h”
#包括
//typedef WrapperPlugin*(*wrapperplugininitype)();这通常在共享库中
静态常量wchar_t*包装器_模块_NAME=L“LibraryB.dll”;
静态常量字符*包装器模块初始化函数;
ClassA::ClassA():
包装器模块(空),
包装器插件(空)
{
}
ClassA::~ClassA()
{
如果(此->包装器模块!=NULL)
{
FreeLibrary(此->包装器模块);
}
}
boolcharpbridge::Initialize()
{
此->包装器模块=LoadLibraryW(包装器模块名称);
if(this->wrapperModule==NULL)
{
返回false;
}
WrapperPlugininitype wrapperPluginInit=reinterpret_cast(GetProcAddress(this->wrapperModule,WRAPPER_模块_INIT_函数_名称));
if(wrapperPluginInit==NULL)
{
返回false;
}
此->wrapperPlugin=wrapperPluginInit();
if(this->wrapperPlugin==NULL)
{
返回false;
}
返回true;
}
外部“C”
{
__declspec(ddlexport)StubA*AExport()
{
如果(!ClassA::GetInstance().Initialize())
{
返回NULL;
}
return&ClassA::GetInstance();
}
}
B.h类
#包括
B类:公共存根B
{
公众:
b类();
~ClassB();
静态类b&GetInstance()
{
静态ClassB实例;
返回实例;
}
私人:
B类(B类常数&);
void运算符=(ClassB常量&);
};
类别b.cpp
#包括“ClassB.h”
#包括
#包括
#包括
ClassB::ClassB()
{
std::流myfile;
myfile.open(“C:\\Users\\USERNAME\\Desktop\\test1.txt”);
myfile您似乎无法在从非托管库管理的库上使用FreeLibrary。因为托管库将启动非托管库不知道的AppDomain。AppDomain使库保持活动状态,因此从未运行析构函数。请参阅答案
将某个对象从非托管调用为托管仍然需要特别注意,因为如果不这样做,将导致异常:0xC002001:字符串绑定无效!请参阅。我所做的是在ClassB作用域中使用静态实例,并在ClassB::GetInstance中使用新运算符对其进行初始化。否则它将不可用不需要初始化。然后我创建了一个函数ClassB::CleanUp,在其中我删除了它。但是,重要的是要用#pragma-managed(push,off)和#pragma-managed(pop)标记整个类(头文件和源文件)为非托管
要仍然能够调用托管方法/类,您必须在源文件中创建一个函数,其中包含#pragma managed(push,on)和#pragma managed(pop)。然后,您可以从非托管类调用此函数。这对我来说仍然很奇怪,因为该函数也是托管的?至少要解释一下为什么您否决了此函数,以便我下次可以做得更好。。嗯,我知道是怎么回事。当您要求志愿者投入他们的空闲时间来帮助您时,最起码的礼貌是发布代码至少,他们可以编译并运行来重新处理问题。这段代码既不编译也不运行。处理起来相当简单,只需自己编译并运行即可。
#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;
};
#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();
}
}
#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&);
};
#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();
}
}