0

我在 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 类并调用它的序列化函数吗?

4

0 回答 0