Python ImportError — undefined symbol — for custom C++ module
I’ve been developing a Python module in C++ using OpenCV 2.3 through 2.4.2, on Ubuntu 11.04. OpenCV was built from source. I’m not using the version of OpenCV from the Ubuntu repositories. My Python module compiles with no issues and is loaded in Python properly. However, when I compile this module on Ubuntu 11.10 or 12.04, I get an ImportError with the message «undefined symbol» when trying to load it in Python. This is how I compile the module:
g++ -fPIC -shared `pkg-config --cflags --libs python` `pkg-config --cflags --libs opencv` -I/usr/local/include/opencv2/legacy -o mymodule.so mymodule.cpp
-I/usr/local/include/opencv -I/usr/local/include /usr/local/lib/libopencv_calib3d.so /usr/local/lib/libopencv_contrib.so /usr/local/lib/libopencv_core.so /usr/local/lib/libopencv_features2d.so /usr/local/lib/libopencv_flann.so /usr/local/lib/libopencv_gpu.so /usr/local/lib/libopencv_highgui.so /usr/local/lib/libopencv_imgproc.so /usr/local/lib/libopencv_legacy.so /usr/local/lib/libopencv_ml.so /usr/local/lib/libopencv_nonfree.so /usr/local/lib/libopencv_objdetect.so /usr/local/lib/libopencv_photo.so /usr/local/lib/libopencv_stitching.so /usr/local/lib/libopencv_ts.so /usr/local/lib/libopencv_video.so /usr/local/lib/libopencv_videostab.so
ImportError: /path/to/service/mymodule.so: undefined symbol: _ZN5CvSVMD1Ev
My understanding is that «undefined symbol» generally means that the given symbol can’t be found in any of the linked libraries. But I know that this symbol is there in libopencv_ml.so because when I run this:
$ nm -g /usr/local/lib/libopencv_ml.so | grep _ZN5CvSVMD1Ev
000000000002fd40 T _ZN5CvSVMD1Ev
$ cat /etc/ld.so.conf.d/libc.conf # libc default configuration /usr/local/lib
$ ldconfig -p | grep opencv | grep ml libopencv_ml.so.2.4 (libc6,x86-64) => /usr/local/lib/libopencv_ml.so.2.4 libopencv_ml.so (libc6,x86-64) => /usr/local/lib/libopencv_ml.so
So can you give me any clue what I might be doing wrong? Has something changed between Ubuntu 11.04 and 11.10 in the manner in which shared libraries are loaded when running Python? Or is this a problem with OpenCV?
Undefined symbol error importing Cython module
I want to make available one of my c++ classes as Python module. The class is declared in a header Foo.h and implemented in a .cpp Foo.cpp . (g++-4.5, Ubuntu x86_64). It’s a very very simple class: Foo.cpp :
Foo::Foo() : alfa(1.0), beta(1) < >Foo::~Foo()
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup( name = 'MyDemo', ext_modules=[ Extension("Foo" sources=["Foo.pyx"], include_dirs=[".","../eigen/"], language="c++"), ], cmdclass = , )
cdef extern from "Foo.h": ctypedef struct c_Foo "Foo": double alfa c_Foo *new_Foo "new Foo" () void del_Foo "delete" (c_Foo *myfoo) cdef class Foo: cdef c_Foo *thisptr # hold a C++ instance which we're wrapping def __cinit__(self): self.thisptr = new_Foo() def __dealloc__(self): del_Foo(self.thisptr)
running build_ext skipping 'Foo.cpp' Cython extension (up-to-date) building 'Foo extension gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I. -I../eigen/ -I/usr/include/python2.6 -c Foo.cpp -o build/temp.linux-x86_64-2.6/Foo.o cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++ g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-x86_64-2.6/Foo.o -o /home/linello/prova/Foo.so
>>> import Foo Traceback (most recent call last): File "", line 1, in ImportError: ./Foo.so: undefined symbol: _ZN4FooD1Ev >>>
I think that _ZN4FooD1Ev is the mangled name of the constructor of Foo but don’t understand how is missing the symbol. I really can’t understand what symbol is missing from the shared object file. And as second point, after the python setup.py build_ext —inplace command, my Foo.cpp file is messed up and contains the cythonized version. How is possible to rename the cythonized file in another format (for example .cxx ) and avoid that linker error? I then modified the Foo.pyx in pFoo.pyx and consequently modified the setup.py , now after the setup command I have the cythonized version of pFoo.pyx in Foo.cxx but when I try to import I get the ImportError: dynamic module does not define init function (initpyFoo) What is wrong with my setup and how is possible to solve my problems?
Receive «undefined symbol» error when loading library with dlopen
I’m writing some code that uses dynamic shared libraries as plugins. My command line for building the shared libraries looks like:
cc -shared -fPIC -o module.so -g -Wall module.c
Within the module, I can call functions that are in any other shared library that has been loaded within the main executable. However I cannot access (exported) functions that are in the executable itself (I get undefined symbol errors). My call to dlopen looks like this:
void *handle = dlopen(plugin, RTLD_NOW);
Can anyone please advise how my module can call back to my executable, without having to put all of the executable’s utility functions into yet another shared library?
3 Answers 3
Correct solution is to add -rdynamic to the link command of the main executable. This will add appropriate option to ld (which, when using GNU ld , happens to be —export-dynamic ).
Adding —export-dynamic directly is technically incorrect: it’s a linker option, and so should be added as -Wl,—export-dynamic , or -Wl,-E . This is also less portable than -rdynamic (other linkers have an equivalent, but the option itself is different).
This solution also applies when using Boost Extensions as boost shared_library class is using dlopen (on Linux) to load library.
I’ve found the answer myself.
I had to add the —export-dynamic flags to the link options for the main executable.
When creating a dynamically linked executable, add all symbols to the dynamic symbol table. The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time.
If you do not use this option, the dynamic symbol table will normally contain only those symbols which are referenced by some dynamic object mentioned in the link.
If you use «dlopen» to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself.
dlopen — Undefined symbol error
In that shared object I refer to a const char* defined in another shared library «SharedLibarary2.so». The Executable, and both the libraries are built using -rdynamic. But I still get the run time error when using dlopen: «/usr/lib/SharedLibarary1.so: undefined symbol» and points to the mangled const char* has the undefined symbol. Whith GDB «info share» I can see that the second library is not loaded at the point of the error. How ever that problem goes away if I do a dlopen on the second library before I do on the first library. Is there a better way to force the loader to load the second library for the unresolved symbol?
yes. Don’t make the library you load rely on something that will only be linked in by another library that you will load using dlopen(). Use a shared object that is loaded the regular way that has that symbol. Does using RTLD_LAZY help by the way?
2 Answers 2
When building a shared library, you can link another inside, e.g. like
gcc -shared -rdynamic lib1*.pic.o -lshared2 -o SharedLibrary1.so
Then check with ldd SharedLibrary1.so
(look e.g. at the output of ldd on your system’s libgtk-3.so.0 for an example)
% ldd /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 linux-vdso.so.1 => (0x00007fff6afff000) libgdk-3.so.0 => /usr/lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f0572628000) libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f0572424000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f057221b000) libpangocairo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f057200e000) libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f0571cd2000) libXi.so.6 => /usr/lib/x86_64-linux-gnu/libXi.so.6 (0x00007f0571ac2000) libXcomposite.so.1 => /usr/lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f05718c0000) libXdamage.so.1 => /usr/lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f05716be000) libXfixes.so.3 => /usr/lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f05714b7000) libatk-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007f0571294000) libcairo-gobject.so.2 => /usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007f057108b000) libcairo.so.2 => /usr/lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f0570d91000) libgdk_pixbuf-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f0570b71000) libpangoft2-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f0570946000) libpango-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f05706f8000) libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f0570459000) libfontconfig.so.1 => /usr/lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f0570222000) libgio-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f056fece000) libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f056fc7e000) libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f056f986000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f056f703000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f056f4e7000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f056f160000) libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f056ef4c000) libXinerama.so.1 => /usr/lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f056ed4a000) libXrandr.so.2 => /usr/lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f056eb42000) libXcursor.so.1 => /usr/lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f056e937000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f056e733000) /lib64/ld-linux-x86-64.so.2 (0x00007f0572f57000) libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f056e512000) libpixman-1.so.0 => /usr/lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f056e28c000) libpng12.so.0 => /lib/x86_64-linux-gnu/libpng12.so.0 (0x00007f056e064000) libxcb-shm.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f056de61000) libxcb-render.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f056dc57000) libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f056da4d000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f056d836000) libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f056d60b000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f056d3eb000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f056d1d5000) libgthread-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0 (0x00007f056cfd2000) libffi.so.5 => /usr/lib/x86_64-linux-gnu/libffi.so.5 (0x00007f056cdc5000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f056cb87000) libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f056c983000) libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f056c77e000)