我想加载我自己的C++动态链接库,这是我的测试代码:
添加.cpp
#include <vector>
using namespace std;
int add(int c)
{
vector<int> v;
int i;
int sum = 0;
for (i = 0; i < c; i++)
{
sum = sum + i;
}
return sum;
}
我执行下面的命令来构建 add.so
:
g++ -fPIC -shared add.cpp -o add.so
然后我尝试使用 dlopen
将它动态链接到我的 C++ 项目:
主要.cpp
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
typedef int (*add_func_ptr)(int);
int main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("./add.so", RTLD_LAZY);
if (!handle)
{
fputs(dlerror(), stderr);
exit(1);
}
add_func_ptr addfun;
addfun = (add_func_ptr)dlsym(handle, "add");
if ((error = dlerror()) != NULL)
{
fputs(error, stderr);
exit(1);
}
printf("%d\n", (*addfun)(2));
dlclose(handle);
}
最后,我编译它:
g++ main.cpp -ldl -o main
然而,当我执行./main
时,我总是得到错误:symbol not found
。
有一个类似的question ,但答案无法解决我的问题。我知道这个问题可能是由 C++ 中的 name mangling 引起的,但我不知道如何解决,我想在动态链接中使用 std::vector
,所以我需要使用 C++而不是 c 来构建 .so 文件。
最佳答案
大多数 C++ 实现使用 name mangling (在错位名称中编码一些类型信息)。
您需要声明 extern "C"
任何与 dlsym
相关(即与之一起使用)的符号(这会禁用该符号上的名称重整)。
所以你的 add.cpp
文件应该在它的 #include
-s 指令之后有如下声明:
extern "C" int add(int c);
顺便说一句,用 nm -D -C add.so
检查你的插件的动态符号表。
当然,extern "C"
函数可以使用 C++ 特性和类型。所以你可以编码
extern "C" int sum_vector_elements(const std::vector<int> &v);
int sum_vector_elements(const std::vector<int> &v) {
int s =0;
for (int x: v) { s += x; };
return s;
}
并在您的主程序中执行一些dlsym(handle, "sum_vector_elements")
。
参见 nm(1) , dlopen(3) , dlsym(3) , C++ dlopen minihowto , Drepper 的 How To Write Shared Libraries , c++filt了解更多。
出于可读性原因,您可以使用 typedef
来定义签名(插件中的 dlsym
可用函数),例如 here .
关于c++ - 与 dlopen 的动态链接 : symbol not found,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49187610/