从使用 dlopen 加载的共享库中引用全局符号

Referencing global symbols from shared library loaded with dlopen

我有一个共享库,我想从主程序中访问符号。例如:

main.c

#include <stdio.h>

void bar(void) { puts("bar"); }

extern void foo(void);

int main(void) {
    foo();
    return 0;
}

foo.c

#include <stdio.h>

extern void bar(void);

void foo(void) {
    puts("foo");
    bar();
}

我编译并且运行喜欢:

gcc -c -fpic foo.c
gcc -shared -o libfoo.so foo.o
gcc -L$(pwd) -o test main.c -lfoo
./test

我得到了我期望的输出:

foo
bar

但是,我必须使用 dlopen()dlsym(),因为我想控制何时加载库。更改的文件是:

main.c

#include <stdio.h>
#include <dlfcn.h>

void bar(void) { puts("bar"); }

int main(void) {
    void *handle = dlopen("./libfoo.so", RTLD_LAZY);
    void (*foo)(void) = (void(*)(void))dlsym(handle,"foo");
    foo();
    return 0;
}

foo.c

#include <stdio.h>
#include <dlfcn.h>

extern void bar(void);

void foo(void) {
    puts("foo");
    bar();
}

我编译并 运行 使用:

gcc -c -fpic foo.c
gcc -shared -o libfoo.so foo.o
gcc -o test main.c -ldl
./test

然而,这次我得到了输出

foo
./test: symbol lookup error: ./libfoo.so: undefined symbol: bar

如何从 libfoo 引用主程序中的符号?

链接时必须添加-rdynamic选项test:

gcc -o test main.c -ldl -rdynamic

来自 here:

-rdynamic Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table. This option is needed for some uses of dlopen or to allow obtaining backtraces from within a program.