【问题标题】:Loading a C++ class with polymorphism using dlsym()使用 dlsym() 加载具有多态性的 C++ 类
【发布时间】:2020-12-06 16:46:13
【问题描述】:

我有一个 C++ 程序,我需要打开一个共享对象 (.so) 并从中加载一个 C++ 类。我已经在互联网上看到了这一点,并且我在 C 和 C++ 中都使用 dlsym() 加载了很多东西,所以我知道一切是如何工作的。但是,我需要做一些细微的改变。我使用 dlsym() 加载的类必须是另一个类的子类,该类在共享对象和主程序使用的标头中定义。这个想法是在运行时加载这个类的一堆不同的自定义版本。在编译时与对象链接不是一种选择。这是我所做的(高度缩写,但所有重要部分都在那里):

BaseClass.h:

class BaseClass {
    public:
        virtual ~BaseClass();
        virtual int function(int, int);
};

ChildClass.h:

extern "C" BaseClass* makechild();

ChildClass.cpp:

class ChildClass : public BaseClass {
    public:
        int function(int a, int b) override { return a + b; }
};

BaseClass* makechild() {
    return new ChildClass();
}

main.cpp:

std::function<BaseClass*(void)> make;

// note that in the actual program I throw a std::runtime_error with
// dlerror() as its message when this goes wrong, and I don't handle it
make = reinterpret_cast<BaseClass*(*)(void)>(dlsym(handle, "makechild"));

BaseClass* myclass = make();

然后我将 ChildClass.cpp 编译为 ChildClass.so(使用 -shared -fpic)并使用 -ldl 和其他一些与警告相关的标志等编译 main.cpp。使用 g++ 和 clang++ 我在运行时遇到两个不同的错误:

  • 用clang++编译后:undefined symbol: _ZN9BaseClassD2Ev
  • 用g++编译后:undefined symbol: _ZTI9BaseClass

用objdump和readelf检查.so文件后,我确认这个符号确实是未定义的:

...
0000000000000000         *UND*  0000000000000000              _ZN9BaseClassD2Ev
...
0000000000000000         *UND*  0000000000000000              _ZTI9BaseClass
...

我不确定这些符号的确切含义。在阅读了一点 ABI 文档之后,似乎第一个可能是 dtor 或其他东西,第二个可能是 ctor 或类本身,类似的东西。无论如何,我并没有明确地尝试加载这些,但我不确定为什么它们是未定义的。是否可以使用 dlsym() 和 C++ 进行这种多态/继承设置?

编辑:感谢评论,我已使用 C++filt 程序发现析构函数丢失(我刚刚添加了 virtual ~BaseClass() = default; 来解决此问题)。现在缺少的一件事是 _ZTI 一个,它是类的类型信息。

【问题讨论】:

  • 使用命令echo _ZTI9BaseClass | c++filt 来解封该名称
  • 您需要为BaseClass析构函数提供定义。
  • @Slava 谢谢!这是一个非常有用的命令,我不知道。
  • @G.M.我现在已经这样做了,但是现在缺少的项目仍然是_ZTI9BaseClass,这似乎是基类的类型信息。
  • BaseClass::function 实现了吗?

标签: c++ class inheritance polymorphism dlsym


【解决方案1】:

事实证明,析构函数和 typeinfo 是未定义的符号。考虑到我做过多少次这样的事情,我应该看到这一点,但没有人是完美的。无论如何,我为解决这个问题所做的只是为BaseClass::~BaseClass 添加= default,为BaseClass::function 添加= 0。非常感谢用户 G.M.在我原来的帖子中的 cmets 中提出这个问题!

【讨论】:

    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 2017-03-28
    • 1970-01-01
    相关资源
    最近更新 更多