将指向对象的指针传递给dll

时间:2018-03-25 01:28:48

标签: c++ c dll visual-studio-2013 unresolved-external

我正在编写这个加载game.dll的Editor.exe程序,获取dll中函数的地址,并将指针传递给Core对象。

gameInitFuncPtr init = 
    (gameInitFuncPtr) GetProcAddress(LoadLibraryA("game.dll"),"gameInit");
init(&core); // core is already instanced somewhere, maybe on the stack

game.dll包含core.h,其中定义了Core类。 Core类已实现并编译为Editor.exe。

在dll方面,从传递的对象指针调用函数会产生未解析的外部符号

game.dll对给定对象指针的调用示例如下:

void gameInit(ldk::Core* core)
{
    _core->renderer.drawText("initializing...");
}

如何编译dll以便它不会尝试查找dll模块中的drawText()实现?

1 - 请注意,这不是关于如何声明指向成员函数的指针的问题。

2 - 我知道如果我传递的结构只有指向方法的指针,那么很容易修复它,但我对此非常好奇。

3 - 我使用的是Microsoft的cl编译器18.00,与 Visual Studio 2013一起提供的

3 个答案:

答案 0 :(得分:0)

目前尚不清楚初始化internalFrame的位置。乍一看_core应该这样做。

声明接口类gameInit,即它应该是抽象的。在后继类中实现它,例如在exe中的CoreImpl。这将修复未解析的外部符号。

答案 1 :(得分:0)

看起来我正在思考它。 编译editor.exe的文件可以声明Core只链接任何类。

struct Core
{
    struct Renderer
    {
        void drawText(const char* text);
    }
    ...
}

但是,由于编辑器和game.dll共享相同的Core.h,我使用宏来修改Core.h成员函数的声明为纯虚拟,例如:< / p>

struct Core
{
    struct Renderer
    {
        virtual void drawText(const char* text) = 0;
    }
    ...
}

所以未解析的外部符号链接错误消失了

但是:我在RUNTIME中没有按预期工作! :(

答案 2 :(得分:-1)

在设置上几乎和您一样,我也遇到了类似的问题-dll和Game分别为dll和Game。以下是有关如何解决此问题的一些说明。

仅调用虚拟方法。如您所指出,如果调用的方法未声明为虚拟方法,则链接器将尝试为其找到一个实现并失败(如果它不在标头中-我们尽量避免的事情)。该方法不需要是抽象的,虚拟的就足够了。另外,请注意,在结构Renderer中,您可以具有非虚拟的方法,只要您不从dll调用它们(如果这样做,链接器就会抱怨)。最好不要有这样的接口,最好有某种API类,该类仅具有虚拟公共方法,这样此类的用户就不会犯错。

从dll使用的所有类都只需要共享或仅是头文件。我的意思是,据我所知,在头文件中声明类没有任何神奇的方法。 ,在cpp中实现,后者被编译为exe,然后从dll使用这些类。例如,如果您有一个自定义字符串类,则它必须位于共享库中。如果只是在exe中,您将无法在dll中实例化它(从函数等中返回它)。解决方案是使用仅标头的类。例如,您的字符串可以在Editor项目的标头中实现,并且此标头可能包含在Game项目中。这样,您基本上可以将相同的代码编译为exe和dll。

要查看一个小型工作示例,请参阅我的带有VS 2017解决方案的存储库,该存储库演示了此确切问题,仅此而已。 repo link

在idTech4引擎-DOOM 3版本here中可以看到此问题的更大示例。它还将游戏用作dll,将引擎用作exe。并且还需要交换指向游戏中使用的引擎系统的指针。该项目很大,但是如果您从头到尾查看项目Game-d3xpGame.h,他们的游戏API都带有一个函数GetGameAPI_t,该函数希望获得{{1 }}具有指向引擎系统的指针的结构,并返回gameImport_t和游戏信息。然后,加载会在Common.cpp

中进行

如您所见,他们在各自的项目中使用共享库gameExport_t来处理诸如idLib之类的事情。 dll中使用的所有引擎类通常都很小,仅在标头中实现(它们大多是结构)。

请注意,id本身正在脱离此体系结构,甚至其最新版本的DOOM 3-DOOM 3 BFG edition都可以编译为单个exe,并且模块是静态库而不是dll。