Consider the following files
# 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)();
}
Calling ./app yields
Calling main_fun...
Calling bar...
Calling foo...
./app: symbol lookup error: ./libdyn.so: undefined symbol: foo
and ldd libmain.so yields
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)
I don't understand why libdyn doesn't have access to foo. libmain links against libso, which provides foo and libdyn is loaded by libmain, so shouldn't foo then be found?
I am interested in solving this problem, however, there are a few constraints. As could be suspected, this is kind of a MWE for my real problem. In my application libmain.so is called using the Java Native Interface. Furthermore, only libmain is user code. libso and libdyn are external libraries that would be very difficult for me to recompile, but it would be doable. Lastly, there isn't a single foo function, but thousands and also global variables that must be shared in the way foo should be shared.