![](/img/trans.png)
[英]Different math symbol bindings with shared library with dlopen and directly linked into executable (Linux)
[英]Providing symbol of linked shared library to shared library opened with dlopen
考虑以下文件
# Makefile
all: libdyn.so libmain.so app
libdyn.so: libdyn.cpp
g++ -fPIC -shared -o libdyn.so libdyn.cpp
libso.so: libso.cpp
g++ -fPIC -shared -o libso.so libso.cpp
libmain.so: libmain.cpp libso.so
g++ -Wl,--no-as-needed -fPIC -shared -o libmain.so libmain.cpp -ldl -L`pwd` -lso
app: main.cpp g++ -o app main.cpp -ldl
g++ -o app main.cpp -ldl
// libdyn.cpp
#include <iostream>
extern "C" {
extern void foo();
void bar() {
std::cout << "Calling foo..." << std::endl;
foo();
}
};
// libso.cpp
#include <iostream>
extern "C" {
void foo() {
std::cout << "Hello from foo" << std::endl;
}
};
// libmain.cpp
#include <iostream>
#include <dlfcn.h>
int main_fun() {
void* handle = dlopen("./libdyn.so", RTLD_LAZY);
void (*bar_ptr)() = reinterpret_cast<void(*)()>(dlsym(handle, "bar"));
std::cout << "Calling bar..." << std::endl;
(*bar_ptr)();
return 0;
}
// main.cpp
#include <iostream>
#include <dlfcn.h>
int main() {
void* handle = dlopen("./libmain.so", RTLD_LAZY);
int (*main_fun_ptr)() = reinterpret_cast<int(*)()>(dlsym(handle, "_Z8main_funv"));
std::cout << "Calling main_fun..." << std::endl;
(*main_fun_ptr)();
}
调用./app
产生
Calling main_fun...
Calling bar...
Calling foo...
./app: symbol lookup error: ./libdyn.so: undefined symbol: foo
和ldd libmain.so
产量
linux-vdso.so.1 (0x00007ffd903f8000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe05cdb8000)
libso.so (0x00007fe05cdb3000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe05cb99000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe05ca4a000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe05ca2f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe05c83b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe05cddf000)
我不明白为什么libdyn
无法访问foo
。 libmain
链接到libso
,它提供foo
和libdyn
由libmain
加载,所以不应该找到foo
吗?
我有兴趣解决这个问题,但是有一些限制。 可以怀疑,这对于我的真正问题来说是一种 MWE。 在我的应用程序中, libmain.so
使用 Java 本机接口调用。 此外,只有libmain
是用户代码。 libso
和libdyn
是我很难重新编译的外部库,但它是可行的。 最后,没有一个单一的foo
function,但有成千上万的全局变量必须以foo
应该共享的方式共享。
在main.cpp
中,使用 dlopen 中的 open RTLD_GLOBAL
。
从手册:
RTLD_GLOBAL
The symbols defined by this shared object will be
made available for symbol resolution
of subsequently loaded shared objects.
编辑:或者,不要将libso.so
作为依赖项链接到libmain.so
,而是从main_fun
调用dlopen
:
dlopen("libso.so", RTLD_LAZY|RTLD_GLOBAL)
或者可能来自共享对象初始化器:
static void init(void) __attribute__((constructor));
static void init(void) {
fprintf(stderr, "libmain constructor %s running\n", __func__);
if (!dlopen("libso.so", RTLD_LAZY|RTLD_GLOBAL)) {
fprintf(stderr, "dlopen(\"libso.so\"): *** %s\n", dlerror());
exit(1);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.