使用 dlsym() 加载具有多态性的 C++ 类

威尔·埃克尔斯

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

基类.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();
}

主.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是该类的类型信息。

威尔·埃克尔斯

事实证明,析构函数和类型信息是未定义的符号。鉴于我做过多少次这样的事情,我应该看到这一点,但没有人是完美的。无论如何,我为解决这个问题所做的只是添加= defaultforBaseClass::~BaseClass= 0for BaseClass::function非常感谢用户 GM 在我原帖的评论中提出这个问题!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在C ++中使用多态性访问类的孙子

C ++多态性-调用具有不同签名的派生类方法

C ++模板方法重载和具有多态性的类访问

嵌套类与不具有多态性的子类之间的C#差异

C#多态性:获取具有相同名称的派生类的属性,而不是基类的字段

C ++多态性:是否可以使用从双重派生类到基类的函数?

Haskell 返回具有类限制的类型多态性

C ++:运算符=具有多态性的重载

具有多态性的C#泛型

extern "C" 用于加载 dlsym 的函数

C#-数组中的类的多态性

C ++多态性:从父类到子类

C ++多态性,派生类的名称解析

使用类型类指定的返回类型多态性

具有多态性的std :: bind和std :: function,基类

如何使用多态性从基类访问派生类向量成员?

通用类多态性

C ++的多态性

当我无法使用基类引用调用派生类方法时,动态多态性有什么用?

具有基于概念的多态性的多重继承 C++

Flutter是否可以对抽象部件使用具有抽象层的多态性?

仅子类具有虚拟方法时使用多态性的问题

为什么我们使用具有多态性的指针?

C ++多态性:派生类调用基类虚拟函数,而不是重写的派生类

C ++多态性将基类指针存储在向量中

怀疑多态性的使用,以及多态性与铸造有何关系?

正常的多态性和使用通用的多态性有什么区别?

具有显式多态性抛出的每个类层次结构的Hibernate表无法获得反射值

C ++多态性:如何测试一个类是否衍生自另一个基类?