将共享库与 dlopen 一起使用 - 共享对象找不到加载程序导出的符号

Posted

技术标签:

【中文标题】将共享库与 dlopen 一起使用 - 共享对象找不到加载程序导出的符号【英文标题】:Using shared libraries with dlopen - shared object cannot find symbol exported by the loading program 【发布时间】:2015-03-06 13:22:35 【问题描述】:

所以,我正在尝试运行以下示例。

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;

它是用下面的makefile编译的

all:
    g++ main.cpp -ldl

然后,我想使用我自己的registerfunc,它的写法如下:

main.h:

extern "C"

    void test();
;

main.cpp

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

void test() 
    registerfunc();

生成文件:

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 ?? ()

这让我有点困惑,至于如何让 test.so 调用由它的被调用者定义的东西。请问您能帮忙吗?

【问题讨论】:

【参考方案1】:

您在这里至少有三个不同的问题:

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

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

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

nm -D a.out | grep ' T '

最后,当你这样做时:

a.out -&gt; g++ -g -fPIC -shared main.cpp -ldl

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

【讨论】:

以上是关于将共享库与 dlopen 一起使用 - 共享对象找不到加载程序导出的符号的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 共享库中隐藏业务对象的实现细节并提供接口

程序中动态加载共享库

Linux 共享库链接错误(未定义符号)

如何将共享库与 --as-needed 与 automake 链接?

dlopen:无法使用静态 TLS 加载更多对象

如何在 Linux 的 QTCreator 中使用 dlopen 打开的共享库中设置断点