Использование общих библиотек с dlopen - общий объект не может найти символ, экспортированный программой загрузки

Итак, у меня есть следующий пример, который я пытаюсь запустить.

header.h

extern "C" {
        void registerfunc();
};

main.cpp

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

using namespace std;

typedef void (*register_func)();

void registerfunc() {
    cout << "register func has been called" << endl;
}

int main() {
    void* lib_handle = dlopen("./test/test.so", RTLD_NOW | RTLD_GLOBAL);

    if(lib_handle == NULL){
            cout << "no such lib:" << dlerror() <<endl;
            return 0;
    }

    register_func reg = (register_func)dlsym(lib_handle, "test");

    if(reg == NULL){
            cout << "Cannot load symbol" <<  dlerror() << endl;;
    } else {
            reg();
    }
    return 0;
}

он скомпилирован с помощью следующего make-файла

all:
    g++ main.cpp -ldl

Затем я хочу использовать registerfunc из своего собственного, так что это написано следующим образом:

main.h:

extern "C"
{
    void test();
};

main.cpp

#include "main.h"
#include "../header.h"

void test() {
    registerfunc();
}

Makefile:

all:
    g++ main.cpp -fPIC -shared -o test.so

Когда я компилирую его таким образом и запускаю a.out (вывод первого main), я получаю:

 no such lib: ./test/test.so: undefined symbol: registerfunc

Однако, если я скомпилирую a.out и test.so, используя следующие команды:

a.out -> g++ -g -fPIC -shared main.cpp -ldl
test.so -> g++ -g main.cpp -fPIC -shared -o test.so ../a.out

то я получаю ошибку сегментации со следующей трассировкой (gdb -ex run a.out):

0x0000000000000001 in ?? ()

Это ставит меня в тупик относительно того, как make test.so вызывает то, что определено вызываемым объектом. Не могли бы вы помочь?


person user905747    schedule 06.03.2015    source источник


Ответы (1)


Здесь у вас как минимум три отдельные проблемы:

  • Меньший из них состоит в том, что у вас есть два файла с именем main.cpp, и не совсем понятно, какая команда относится к какому файлу в вашем вопросе.

  • Более серьезная проблема заключается в том, что вы ожидаете, что test.so будет связываться с registerfunc в a.out, но функция не экспортируется из a.out , если какая-то разделяемая библиотека, участвующая в ссылках на ссылки, функция, или вы связываете с -Wl,--export-dynamic (который экспортирует все функции). Это настоящее решение.

    Вы можете увидеть, какие функции экспортируются из вашего a.out, с помощью этой команды:

    nm -D a.out | grep ' T '

  • Наконец, когда вы это сделаете:

    a.out -> g++ -g -fPIC -shared main.cpp -ldl

    вы фактически создаете общую библиотеку (с именем a.out), а не исполняемый файл. Запуск такой разделяемой библиотеки, как если бы это был исполняемый файл, приводит к сбою, который вы наблюдали.

person Employed Russian    schedule 16.03.2015