【问题标题】:Use of application class within shared library在共享库中使用应用程序类
【发布时间】:2021-07-01 15:00:56
【问题描述】:

我正在尝试创建一个“游戏平台”,让用户可以选择要玩的游戏以及渲染它的图形库。这些游戏和图形库被实现为动态库,在运行时加载。我们将把游戏平台称为核心。 共享库包含在运行时使用 RTLD_LAZY 标志加载的类,但是如果我使用 RTLD_NOW 加载它,程序将正确编译。 我遵循this 教程以避免名称混淆,并且像这样使用共享库上定义的类。 目前,如果方法不调用核心类的任何方法(仅使用类的参数),它就可以正常工作。 (见下面的代码)

// Working code

void libNCurses::refreshScreen(Core *core)
{
  if (core->input != Input::None)
        mvaddch(0,0,'c');
  else
        mvaddch(0,0,' ');
  refresh();
}

但是当我想调用 Core 类的某个方法时,程序崩溃并抱怨未定义的符号(使用的方法的符号)。 (见下面的代码)

// Not working code

void libNCurses::refreshScreen(Core *core)
{
  std::vector<Object *> objs = core->getObjects();

  for (auto obj = objs.begin(); obj != objs.end(); obj++)
      mvaddch(10, 10, 'O');
  if (core->input != Input::None)
        mvaddch(0,0,'c');
  else
        mvaddch(0,0,' ');
  refresh();
}

当然,Core 标头包含在共享库中。 任何人都可以向我解释为什么会发生这种情况以及如何解决它?

【问题讨论】:

  • 您的结果描述需要更清楚,通常“程序崩溃”表示运行时错误,但未定义符号通常仅限于编译时。您能否澄清一下您何时收到错误,以及它实际上是由您的程序还是由构建工具产生的?
  • 程序崩溃并抱怨未定义的符号,因为共享库在运行时加载了 RTLD_LAZY 标志。我已将其更改为在调用 dlopen(使用 RTLD_NOW)时加载所有符号,并且编译它没有问题。当调用 core->getObjects() 方法时,它继续抱怨。
  • 显示插件和主程序的编译和链接命令(例如g++GCC 的选项)。提供一些minimal reproducible example。阅读Drepper's paper How to write shared libraries。并使用dlerror。或许可以在RefPerSys 的源代码中寻找灵感。你的操作系统是 Linux 的吗?
  • 当前使用 WSL2。编译通过makefile 完成。链接在 core class 内的运行时完成。 IGfxLibraryIGLibraryclasses contained on the shared libs 的接口。我会检查 Drepper 的论文并检查 RefPerSys 源代码。

标签: c++ shared-libraries dlopen name-mangling


【解决方案1】:

好的,在阅读了Drepper's paper How to write shared libraries 之后,我发现了问题所在。 在 C++ 中,方法没有链接。程序和库也没有其他链接的方法。该补丁是使用vtable。如果方法是虚拟的,程序会检查对象的 vtable 并在那里找到函数地址。 我可以使用 lib 的方法,因为为了避免名称修改,我使用了 lib 的接口,但不是以其他方式。我希望这个答案对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多