繁体   English   中英

将链接共享库的符号提供给使用 dlopen 打开的共享库

[英]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 ,它提供foolibdynlibmain加载,所以不应该找到foo吗?

我有兴趣解决这个问题,但是有一些限制。 可以怀疑,这对于我的真正问题来说是一种 MWE。 在我的应用程序中, libmain.so使用 Java 本机接口调用。 此外,只有libmain是用户代码。 libsolibdyn是我很难重新编译的外部库,但它是可行的。 最后,没有一个单一的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM