Accessing .so libraries using dlopen() throws undefined symbol error
Most likely, libCamera.so
uses a symbol defined in a shared library without depending on that library.
Find a culprit. Take a real executable which links against
libCamera.so
(and it works). List its dependencies withldd /path/to/executable
. Among them should be a library which has a definition forZTVN10_cxxabiv117__class_type_infoE
(usegrep
to select likely candidates,nm -D
on a library to be sure). That library won't be in the list shown byldd ./libCamera.so
.Solve a problem. Load the library found in step 1 by
dlopen
first (useRTLD_GLOBAL
there as well).If there is a problem with another symbol, goto step 1.
If newly-added libraries have the same problem too, goto step 1.
Tell library authors to please fix their linking.
It could also happen that one of the prerequisites in ldd ./libCamera.so
got upgraded and lost a symbol definition (maybe it was recompiled with a compiler which does name mangling differently). Then you won't find the culprit in step 1, and there is no solution but downgrading something again.
C++ linux: dlopen can't find .so library
Read the dlopen(3) man page (e.g. by typing man dlopen
in a terminal on your machine):
If filename contains a slash ("/"), then it
is interpreted as a (relative or absolute) pathname. Otherwise, the
dynamic linker searches for the library as follows (see ld.so(8) for
further details):
o (ELF only) If the executable file for the calling program
contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
then the directories listed in the DT_RPATH tag are searched.
o If, at the time that the program was started, the environment
variable LD_LIBRARY_PATH was defined to contain a colon-separated
list of directories, then these are searched. (As a security
measure this variable is ignored for set-user-ID and set-group-ID
programs.)
o (ELF only) If the executable file for the calling program
contains a DT_RUNPATH tag, then the directories listed in that
tag are searched.
o The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
checked to see whether it contains an entry for filename.
o The directories /lib and /usr/lib are searched (in that order).
So you need to call dlopen("./libLibraryName.so", RTLD_NOW)
-not just dlopen("libLibraryName.so", RTLD_NOW)
which wants your plugin to be in your $LD_LIBRARY_PATH
on in /usr/lib/
etc .... - or add .
to your LD_LIBRARY_PATH
(which I don't recommend for security reasons).
As Jhonnash answered you should use and display the result of dlerror
when dlopen
(or dlsym
) fails:
void* dlh = dlopen("./libLibraryName.so", RTLD_NOW);
if (!dlh)
{ fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(EXIT_FAILURE); };
You might want to read some books like Advanced Linux Programming to get some knowledge about Linux system programming in general.
Import c-modules from embedded Python interpreter (pybind11) in a shared object raises an undefined symbol exception
I've found a solution. Knowing that it was not tied to numpy halped quite a lot to switch the focus on the real problem: symbol missing. Taking the suggestion from this answer and in particular this point:
Solve a problem. Load the library found in step 1 by dlopen first (use RTLD_GLOBAL there as well).
I've modified the minimum example as follows:
// main.cc
#include "pybind11/embed.h"
#include <dlfcn.h>
namespace py = pybind11;
extern "C" {
void * python;
int create() {
python = dlopen("/usr/lib/x86_64-linux-gnu/libpython3.8.so", RTLD_NOW | RTLD_GLOBAL);
return 0;
}
int destroy() {
dlclose(python);
return 0;
}
int main() {
py::scoped_interpreter guard{};
auto py_module = py::module::import("numpy");
auto version = py_module.attr("__version__");
py::print(version);
return 0;
}
}
// load.cc
#include <dlfcn.h>
int main() {
void * lib = dlopen("./libissue.so", RTLD_NOW | RTLD_DEEPBIND);
int(*fnc)(void) = (int(*)(void))dlsym(lib, "main");
int(*create)(void) = (int(*)(void))dlsym(lib, "create");
int(*destroy)(void) = (int(*)(void))dlsym(lib, "destroy");
create();
fnc();
destroy();
dlclose(lib);
return 0;
}
(obviously in cmake I had to add ${CMAKE_DL_LIBS}
as target link library for issue
target).
Using Qt5 in a library
Ok I found the solution. Since I use different folders for the header and the source files, I have to manually specify where is the file containing the qt code.
QT5_WRAP_CPP( MOCS_HDRS ${INCLUDE_DIR}/UIWindow.h )
Linker error while working with dynamic class loading in C++
You defined vector<polygon> t;
in main.cpp
, which will make it to link against polygon
's ctor/dtor, that's the link error.
To resolve the issue:
- Either follow @robert's answer to directly link
polygon.cpp
- Or avoid use the complete type of
polygon
in yourmain.cpp
.
So you should define vector<polygon*> t;
instead, and push/pop polygon*
to/from the vector.
And you should not forget to call destroy_triangle()
when you pop from the vector, otherwise you have memory leak.
Related Topics
Sort Files Numerically in Bash
Embed Icc Color Profile in PDF
How Is the Address of the Text Section of a Pie Executable Determined in Linux
How to Read Just a Single Character in Shell Script
How to Increase the /Proc/Pid/Cmdline 4096 Byte Limit
Possible Values for 'Uname -M'
How to Disable Socket Creation for a Linux Process, for Sandboxing
How Does Execve Call Dynamic Linker/Loader (Ld-Linux.So.2)
Need to Get the Dates of All Mondays in a Year
Shell Script Get Ctrl+Z with Trap
Keep Meteor Running on Amazon Ec2
Docker Alpine Executable Binary Not Found Even If in Path
How to Increase the /Proc/Pid/Cmdline 4096 Byte Limit
Difference Between Bash Pid and $$