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



我想为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("%dn", (*addfun)(2));
    dlclose(handle);
}

最后,我编译它:

g++ main.cpp -ldl -o main

但是,当我执行./main时,我总是收到错误:symbol not found

有一个类似的问题,但答案无法解决我的问题。我知道问题可能是由C++中的名称重整引起的,但我不知道如何解决,我想在动态链接中使用std::vector,所以我需要使用C++而不是c来构建.so文件。

大多数C++实现都使用名称重整(在损坏的名称中对某些类型信息进行编码(。

您需要声明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-able函数(,如下所示。

最新更新