1

我想为 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

然后我尝试将它动态链接到我的 C++ 项目dlopen

主文件

#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.

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

4

1 回答 1

3

大多数 C++ 实现使用名称重整(在重整名称中编码一些类型信息)。

您需要声明extern "C"与(即与)相关的任何符号dlsym(这会禁用该符号上的名称修饰)。

因此,您的 文件应在其-s 指令add.cpp之后具有以下声明:#include

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 的如何编写共享库c++filt了解更多信息。

出于可读性原因,您可以使用此处typedef定义签名(dlsym插件中的 -able 函数)。

于 2018-03-09T06:53:48.200 回答