Python ImportError-未定义符号-用于自定义C ++模块

问题描述 投票:21回答:1

我一直在Ubuntu 11.04上使用OpenCV 2.3到2.4.2开发C ++中的Python模块。 OpenCV是从源代码构建的。我没有使用来自Ubuntu存储库的OpenCV版本。

我的Python模块可以正常编译,并且已正确加载到Python中。但是,当我在Ubuntu 11.10或12.04上编译此模块时,尝试在Python中加载该模块时,出现消息“未定义符号”的ImportError。

这是我编译模块的方式:

g++ -fPIC -shared `pkg-config --cflags --libs python` `pkg-config --cflags --libs opencv` -I/usr/local/include/opencv2/legacy -o mymodule.so mymodule.cpp

这是“ pkg-config --cflags --libs opencv”的输出]

-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

我的理解是,“未定义符号”通常意味着在任何链接的库中都找不到给定的符号。但我知道libopencv_ml.so中存在此符号,因为当我运行此符号时:

$ nm -g  /usr/local/lib/libopencv_ml.so | grep _ZN5CvSVMD1Ev

我得到:

000000000002fd40 T _ZN5CvSVMD1Ev

/ usr / local / lib似乎在动态链接器缓存中。

$ cat /etc/ld.so.conf.d/libc.conf 
# libc default configuration
/usr/local/lib

so文件也位于缓存中。

$ 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

所以您能给我任何提示我做错了什么吗? Ubuntu 11.04和11.10之间在运行Python时加载共享库的方式有所变化吗?还是OpenCV有问题?

c++ python opencv shared-libraries
1个回答
21
投票

解决方案是在g ++命令行上将生成的模块名称放在它依赖的其他模块之前。

g++ -fPIC -shared -o mymodule.so mymodule.cpp `pkg-config --cflags --libs python` `pkg-config --cflags --libs opencv` -I/usr/local/include/opencv2/legacy

gcc手册页说到-l选项,

这在命令中您写此选项的位置会有所不同;的链接器按顺序搜索和处理库和目标文件他们被指定。因此,foo.o -lz bar.o在文件foo.o但在bar.o之前。如果bar.o引用z中的函数,则那些功能可能无法加载。

由于mymodule.so的名称是在应该链接到的库之前提供的,因此它们实际上都没有链接到生成的.so文件。

感谢@ J.F.Sebastian指出-l的工作原理。

© www.soinside.com 2019 - 2024. All rights reserved.