【问题标题】:Loading derived polymorphic class using dlopen使用 dlopen 加载派生的多态类
【发布时间】:2018-09-27 14:10:17
【问题描述】:

在 C++ 代码中,我试图拥有一个定义多态基类的主模块,它在运行时为它动态加载派生类。主模块有类似的东西:

class Base {
public:
    virtual ~Base();
    virtual int f() = 0;
};

int main() {
    auto make_a_ptr = /* load function pointer make_a from module using dsym */;
    Base* a = make_a_ptr();
    std::cout << a->f() << std::endl;
    delete a;
}

动态加载的外部模块有:

class A : public Base {
public:
    int f() {
        return 123;
    }
};

extern "C" Base* make_a() {
    return new A;
}

这样的系统是否可以在 Linux 上运行,而无需额外的动态链接步骤?因为这里只有make_a是使用dlsym()显式加载的,但是主模块也会调用A::f()A::~A(),访问A的v-table。即使没有明确加载这些符号,这仍然有效吗?

在 Windows 平台上是否可能有类似的系统?

【问题讨论】:

  • Windows 上的插件工作方式不同,插件使用的主程序的功能可能需要dllimportdllexport 注释。这会产生巨大的不同。顺便说一句,您的系统可以在 Linux 上运行,因为您将主程序与 -rdynamic 链接。阅读莱文的Linkers and loaders 书。注意名称篡改。
  • 标准库必须动态链接dll和宿主应用程序,否则每个部分都会有自己的堆,在清理过程中可能会出现问题。
  • "调用 A::f() 和 A::~A()," 具体来说,您将使用删除A::~A(),该函数执行delete a_ptr;几乎。这是一个不同的析构函数条目。 (用 vtable 打印编译。或者检查 asm 代码。)

标签: c++ linux linker dynamic-linking dlopen


【解决方案1】:

在 C++ 代码中,我试图拥有一个定义多态基类的主模块,该基类在运行时为其动态加载派生类。

到目前为止,一切都很好。当心所有常见的警告 - 其中包括:

  • 编译插件时使用相同的编译器和库版本。至少要确保 ABI 兼容。

  • 在 Windows 上执行此操作时链接到共享的 c++ 运行时。

  • windows 将需要 ddlexport/dllimport 声明属性。

  • 使用 -fPIC 编译 linux 共享库

  • 确保延迟加载符号名称以避免冲突(例如,如果 2 个共享库有一个名为 make_a 的导出函数。

这样的系统是否可以在 Linux 上运行,而无需额外的动态链接步骤?

是的

在 Windows 平台上是否可能有类似的系统?

是的。同样,请查看注意事项并进行一些研究。

这里有一些很好的答案:Is there an elegant way to avoid dlsym when using dlopen in C?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 2020-11-28
    • 2011-08-25
    • 1970-01-01
    相关资源
    最近更新 更多