Поиск символа с помощью dlsym для символа в пространстве имен - PullRequest
0 голосов
/ 20 июня 2019

У меня есть динамическая библиотека, которую я хочу загрузить. Я определил функцию add():

#include <iostream>
#include "mymath.h"

#define EXPORT __attribute__((visibility("default")))


EXPORT
int mymath::add(int a, int b) {
    return a + b;
}

Этот символ находится в пространстве имен с именем mymath:

namespace mymath {
    int add(int, int);
}

Я скомпилировал эту библиотеку с помощью следующей команды:

llvm-g++ -Iinclude -dynamiclib -std=c++17 src/mymath.cpp -current_version 1.0 -compatibility_version 1.0 -fvisibility=hidden -o bin/mymath.dylib

Теперь я хочу использовать его в другой программе, загружающей этот символ во время выполнения. Я пришел к следующему коду:

#include <iostream>
#include <dlfcn.h>
#include "mymath.h"

int main() {
    const char* libName = "bin/mymath.dylib";
    void *libHandle;
    std::cout << "# main() starts" << std::endl;
    libHandle = dlopen(libName, RTLD_NOW);
    if(libHandle == NULL) {
        std::cerr << "Error opening mymath:\n" << dlerror() << std::endl;;
        return 1;
    }
    void (*mymath_add) = dlsym(libHandle, "mymath:add");
    if(mymath_add == NULL) {
        std::cerr << "Error opening while getting address of mymath::add:\n" << dlerror() << std::endl;;
        return 2;
    }
    std::cout << "# main() exits" << std::endl;
    return 0;
}

И получить эту ошибку при запуске

 $ make
clang++ -Wall -Wextra -std=c++17 -g -Iinclude -Llib src/main.cpp -o bin/main
 wgonczaronek  Wiktor-Gonczaronek  ~/Projects/…/macos-pt2  master  ? 
 $ ./bin/main
# main() starts
Error opening while getting address of mymath::add:
dlsym(0x7ffac9402a90, mymath:add): symbol not found

Я пробовал с символами, которые я нашел с помощью команды nm, но получаю ту же ошибку. Как я могу загрузить этот символ, используя пространство имен?

1 Ответ

1 голос
/ 20 июня 2019

См. Эту страницу для лучшего объяснения (https://en.wikipedia.org/wiki/Name_mangling).

Имена символов искажены, когда пропущены в библиотеку. В C ++ искажение имен кодирует пространства имен, аргументы шаблона (если есть), аргументы функции (если есть). Это создаст странный символ, такой как _ZN9Wikipedia7article6formatE. C ++ mangling определяется реализацией и может меняться от компилятора к компилятору, поэтому попытка декодировать его в лучшем случае рискованна. Я предлагаю переместить функцию из пространства имен и добавить префикс extern "C", чтобы вызвать искажение имен в стиле C. Название в стиле C хорошо определено, стандартно и будет работать с любым компилятором. Так

extern "C" int add(int a, int b) {
    return a + b;
}

и

void (*mymath_add) = dlsym(libHandle, "_add");
...