我在 Windows (DLL) 上使用带有动态库的谷物时遇到问题。我已阅读谷物网站上的文档。但是,所有文档和示例都隐式链接 DLL,而我需要能够显式链接我的 DLL。我制作了一个示例项目来向您展示我的设置以及我卡在哪里。
该项目分为三个项目,2个DLL和一个可执行文件。第一个 DLL (Object.dll) 包含一个名为 Object 的基类。该 DLL 隐式链接到第二个 DLL (Script.dll),后者实现了一个名为 Script 的派生类。然后将此 DLL 显式链接到可执行文件 (Main.exe)。
对象.dll:
对象.h
#pragma once
class __declspec(dllexport) Object
{
public:
Object();
virtual ~Object();
int so;
virtual void foo() = 0;
template<class Archive>
void serialize(Archive& ar)
{
ar(so);
}
};
Object.cpp 是空的,所以我省略了它。
脚本.dll:
脚本.h
#pragma once
#include "Object.h"
class Script : public Object
{
public:
Script();
~Script();
void foo() override;
template<class Archive>
void serialize(Archive& ar)
{
ar(cereal::base_class<Object>(this));
}
};
脚本.cpp
#include "Script.h"
Script::Script()
{
}
Script::~Script()
{
}
void Script::foo()
{
}
extern "C" __declspec(dllexport) Object* CreateObject()
{
return new Script();
}
extern "C" __declspec(dllexport) void DeleteObject(Object* obj)
{
delete obj;
obj = nullptr;
}
主程序
#include "Object.h"
#include "Windows.h"
#include "cereal/archives/xml.hpp"
#include "cereal/types/memory.hpp"
typedef Object* (__cdecl *CREATEFUNCTION)();
typedef void(__cdecl *DELTEFUNCTION)(Object*);
using namespace std;
int main()
{
std::string dll("DLL.dll");
HINSTANCE dllHandle = LoadLibraryA(dll.c_str());
if (dllHandle == nullptr)
{
cout << "Couldn't load the DLL of the script " << endl;
return 1;
}
CREATEFUNCTION CreateObject = reinterpret_cast<CREATEFUNCTION>(GetProcAddress(dllHandle, "CreateObject"));
if (CreateObject == nullptr)
{
cout << "Couldn't load the CreateObject() function" << endl;
return 1;
}
DELTEFUNCTION DeleteObject = reinterpret_cast<DELTEFUNCTION>(GetProcAddress(dllHandle, "DeleteObject"));
if (DeleteObject == nullptr)
{
cout << "Couldn't load the DeleteObject() function" << endl;
return 1;
}
std::shared_ptr<Object> obj = std::shared_ptr<Object>(CreateObject(), DeleteObject);
cereal::XMLOutputArchive oAr(std::cout);
oAr(obj);
return 0;
}
当然,目前它会抛出异常 UNREGISTERED_POLYMORPHIC_EXCEPTION,因为我没有注册我的 Script 类。这也是我的问题,根据我所阅读的内容,我应该将宏 CEREAL_REGISTER_DYNAMIC_INIT 添加到我调用 CEREAL_REGISTER_TYPE 的源文件中,这将是 Script.h 文件,因为我无法将其添加到源文件中多态性文档。我还应该将 CEREAL_FORCE_DYNAMIC_INIT 添加到包含在主应用程序中的标头中,但我没有在任何地方包含 Script.h 文件。
我试图将每个宏放在不同的地方(不包括在 main.exe 中),但我没有让它工作。有人知道这两个函数应该去哪里以便我可以注册我的 Script 类并调用它的序列化函数吗?