c++ - 使用 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
编译 main.cpp 。-ldl
使用 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
该类的类型信息。
解决方案
事实证明,析构函数和 typeinfo 是未定义的符号。考虑到我做过多少次这样的事情,我应该看到这一点,但没有人是完美的。无论如何,我为解决这个问题所做的只是添加= default
forBaseClass::~BaseClass
和= 0
for BaseClass::function
。非常感谢用户 GM 在我原来的帖子的评论中提出这个问题!
推荐阅读
- php - 在 Wordpress 中加载页面之前检查 cookie
- firebase - 使用 firebase/auth 在我的 Ionic 5 移动应用程序中无法再登录 Facebook
- validation - 是的 vs Joi 用于前端验证
- android - 签署 Android apk 时从管道访问 Azure DevOps 上的安全文件
- javascript - 为什么这个设置器在我代理它时没有给我截获的值?
- java - Java Jpa 自定义实体属性转换器和规范
- python - 熊猫移动平均计算缺少日期?
- java - 合并 HashMap 的键
- python-3.x - 在从 Big Query 读取的 Apache 光束管道中将浮点数转换为字符串
- encryption - 使用智能合约作为 ACL 加密/解密存储在 IPFS 上的数据