gpt4 book ai didi

c++ - 将单例实例共享到共享库而不导出它

转载 作者:行者123 更新时间:2023-11-28 02:20:56 25 4
gpt4 key购买 nike

我正在寻找一种共享单例实例的替代方法在主要可执行文件和 dll 之间。

我的项目目前包含几个链接到可执行文件的静态库,如下所示:

  common.lib (holds singletons)
/ \
/ \
v \
tools.exe \
V
database.lib (holds singletons)
|
V
shared.lib (holds singletons)
/
/
|
v
game.lib (holds singletons)
|
v I-- Extension.dll
server.exe <---I-- Extension.dll (dynamic loaded extensions)
I-- Extension.dll
^
|
+--------------------------------------------------------+
I Extensions loaded through LoadLibrary & dlopen I
I need to have access to the singletons instantiated in: I
I common.lib, database.lib, shared.lib and game.lib I

静态库提供了几个我想暴露给动态加载的 dll 的单例,它们总是与主 exe 二进制兼容

我不能只将静态库转换为动态库,因为它会破坏很多并且需要付出太多努力。我目前的做法是将静态单例 getter :

class Log
{
public:
static Log* instance();
};

变成这样的东西:

class Log { };

__declspec(dllexport) Log* instance();

并通过单独的动态库导出单例实例:

common_inst.dllcommon.lib 导出单例。

game_inst.dllgame.lib 导出单例。

这种方法可行,但我对此并不满意。

是否有另一种跨平台兼容的可能性,可以在不通过 dllexport 导出的情况下将单例共享到共享库?

最佳答案

如果您真的不想在主代码中包含任何 DLL 或导出,您可以使用虚函数方法。

假设每个扩展都有一个用于初始化的导出函数:

DLLEXPORT void InitExtension(MainProgramInfo info);

现在您必须将您的扩展程序想要访问的所有内容添加到传递的结构中:

struct MainProgramInfo {
Game *game;
ScriptEngine *script_engine;
ShaderCompiler *shader_compiler;
...
};

请注意,此处描述的类未导出,但它们的声明必须可用于编译您的扩展。事实上,您甚至可以使用简化版的头文件来编译您的扩展,但您必须确保对于每个类,其所有虚方法都以相同的方式和相同的顺序声明。

虚方法调用只需要:

  1. 指向适当类型对象的有效指针(在运行时),
  2. 方法的正确签名(在编译时),
  3. 方法在虚函数表中的索引(在编译时确定)。

与普通的函数调用不同,它不需要知道函数的地址,因此您不需要导出虚函数来调用它们。

因此,当您的扩展程序收到 MainProgramInfo 中的指针时,它可以开始调用这些对象的虚拟方法,而无需链接器直接使用它们。请注意,没有必要将每个对象都放入 MainProgramInfo:您可以只将顶级单例放在那里,并且您的扩展可以使用它的虚函数来获取指向其他对象/单例的指针:

class Game {
...
virtual Renderer *GetRenderer() const;
virtual ScriptEngine *GetScriptEngine() const;
virtual ShaderCompiler *GetShaderCompiler() const;
...
};

只有当您的编译器在您的主代码和扩展中以相同的方式生成虚方法的索引时,这种方法才有效。 C++ 标准保证这种方法的正确性。它由 GCC ABI 保证(参见 this bug )。此外,它在 Doom 3 中被广泛使用以实现游戏模组,因此它也适用于 MSVC。

关于c++ - 将单例实例共享到共享库而不导出它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32503692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com