linux 与dlopen的动态链接:找不到符号

j0pj023g  于 2024-01-06  发布在  Linux
关注(0)|答案(1)|浏览(133)

我想加载我自己的C++动态链接库,这里是我的测试代码:
add.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++项目:
main.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中的名称mangling引起的,但我不知道如何解决它,我想在动态链接中使用std::vector,所以我需要使用C而不是C来构建.so文件。

yws3nbqq

yws3nbqq1#

大多数C++实现都使用name mangling(将一些类型信息编码到变形名称中)。
您需要声明extern "C"任何与dlsym相关的符号(即与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's How To Write Shared Librariesc++filt了解更多信息。
出于可读性的考虑,您可以使用typedef来定义(插件中支持dlsym的函数的)签名,如here

相关问题