使用 dlsym() 加载具有多态性的 C++ class
Loading a C++ class with polymorphism using dlsym()
我有一个 C++ 程序,我需要打开一个共享 object (.so) 并从中加载一个 C++ class。我已经在 Internet 上看到这样做,并且我在 C 和 C++ 中使用 dlsym() 加载了很多东西,所以我知道一切是如何工作的。但是,我需要做一些细微的差别。我用 dlsym() 加载的 class 必须是另一个 class 的 child class,它在共享 [=] 使用的 header 中定义67=] 和主程序。这个想法是在运行时加载这个 class 的一堆不同的自定义版本。在 compile-time 处与 object 链接不是一个选项。这是我所做的(严重缩写,但所有重要部分都在那里):
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
),然后我将 main.cpp 编译为 -ldl
和其他一些 warning-related旗帜之类的。使用 g++ 和 clang++ 我在运行时遇到两个不同的错误:
- 用clang++编译后:
undefined symbol: _ZN9BaseClassD2Ev
- 用g++编译后:
undefined symbol: _ZTI9BaseClass
用objdump和readelf检查.so文件后,确认这个符号确实是未定义的:
...
0000000000000000 *UND* 0000000000000000 _ZN9BaseClassD2Ev
...
0000000000000000 *UND* 0000000000000000 _ZTI9BaseClass
...
我不确定这些符号的确切含义。在稍微阅读了 ABI 文档之后,似乎第一个可能是 dtor 或其他东西,第二个可能是 ctor 或 class 本身,类似的东西。无论如何,我并没有明确地尝试加载这些,但我不确定为什么它们是未定义的。是否可以使用 dlsym() 和 C++ 执行此 polymorphism/inheritance 设置?
编辑: 感谢评论,我使用 C++filt 程序发现缺少析构函数(我只是添加了 virtual ~BaseClass() = default;
来修复那)。现在缺少的一件事是 _ZTI
一个,它是 class.
的类型信息
事实证明,析构函数和类型信息是未定义的符号。考虑到我做过多少次这样的事情,我应该看到这一点,但没有人是完美的。不管怎样,我所做的就是为 BaseClass::~BaseClass
添加 = default
,为 BaseClass::function
添加 = 0
。非常感谢用户 G.M。在我原来的评论中 post 提出这个问题!
我有一个 C++ 程序,我需要打开一个共享 object (.so) 并从中加载一个 C++ class。我已经在 Internet 上看到这样做,并且我在 C 和 C++ 中使用 dlsym() 加载了很多东西,所以我知道一切是如何工作的。但是,我需要做一些细微的差别。我用 dlsym() 加载的 class 必须是另一个 class 的 child class,它在共享 [=] 使用的 header 中定义67=] 和主程序。这个想法是在运行时加载这个 class 的一堆不同的自定义版本。在 compile-time 处与 object 链接不是一个选项。这是我所做的(严重缩写,但所有重要部分都在那里):
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
),然后我将 main.cpp 编译为 -ldl
和其他一些 warning-related旗帜之类的。使用 g++ 和 clang++ 我在运行时遇到两个不同的错误:
- 用clang++编译后:
undefined symbol: _ZN9BaseClassD2Ev
- 用g++编译后:
undefined symbol: _ZTI9BaseClass
用objdump和readelf检查.so文件后,确认这个符号确实是未定义的:
...
0000000000000000 *UND* 0000000000000000 _ZN9BaseClassD2Ev
...
0000000000000000 *UND* 0000000000000000 _ZTI9BaseClass
...
我不确定这些符号的确切含义。在稍微阅读了 ABI 文档之后,似乎第一个可能是 dtor 或其他东西,第二个可能是 ctor 或 class 本身,类似的东西。无论如何,我并没有明确地尝试加载这些,但我不确定为什么它们是未定义的。是否可以使用 dlsym() 和 C++ 执行此 polymorphism/inheritance 设置?
编辑: 感谢评论,我使用 C++filt 程序发现缺少析构函数(我只是添加了 virtual ~BaseClass() = default;
来修复那)。现在缺少的一件事是 _ZTI
一个,它是 class.
事实证明,析构函数和类型信息是未定义的符号。考虑到我做过多少次这样的事情,我应该看到这一点,但没有人是完美的。不管怎样,我所做的就是为 BaseClass::~BaseClass
添加 = default
,为 BaseClass::function
添加 = 0
。非常感谢用户 G.M。在我原来的评论中 post 提出这个问题!