Динамическая связь с dlopen: символ не найден

Я хочу загрузить свою собственную библиотеку динамических ссылок для 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

Затем я пытаюсь динамически связать его с моим C++ проектом dlopen:

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,

Есть похожий вопрос, но ответ не смог решить мою проблему. Я знаю, что проблема может быть вызвана искажением имени в C++, но я не знаю, как ее решить, я хочу использовать std::vector в динамической ссылке, поэтому мне нужно использовать C++ вместо c для создания.so файла.

1 ответ

В большинстве реализаций C++ используется искажение имени (для кодирования некоторой информации о типе в искаженном имени).

Вы должны объявить extern "C" любой символ, связанный с (то есть используемый с) dlsym (это отключает искажение имени для этого символа).

Так что ваши 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), мини- шоу dlopen на C++, Drepper's How to Write Shared Libraries, C++ Filter для получения дополнительной информации.

Для удобства чтения вы можете использовать typedef определить подписи (из dlsym -функции в плагинах) как здесь.

Другие вопросы по тегам