将共享库与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;
}

它是用以下生成文件编译的

all:
    g++ main.cpp -ldl

然后,我想使用我自己的so中的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-runa.out):

0x0000000000000001 in ?? ()

这让我有点困惑,不知道如何让test.so调用被调用者定义的东西。你能帮忙吗?

这里至少有三个单独的问题:

  • 较小的一个是,您有两个名为main.cpp的文件,不完全清楚哪个命令指的是问题中的哪个文件。

  • 更大的问题是,您希望test.so在a.out中绑定到registerfunc,但该函数不会从a.out导出,除非参与链接的某个共享库引用了该函数,您使用-Wl,--export-dynamic链接(导出所有函数)。这才是真正的解决方案。

    您可以使用以下命令查看从a.out导出的功能:

    nm -D a.out | grep ' T '

  • 最后,当你这样做时:

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

    您实际上是在创建一个共享库(名为a.out),而不是一个可执行文件。将这样一个共享库当作可执行文件来运行会导致您所观察到的崩溃。

相关内容

  • 没有找到相关文章

最新更新