J'ai développé un Python en C++ utilisant OpenCV 2.3 à 2.4.2, sur Ubuntu 11.04. OpenCV a été construit à partir des sources. Je n'utilise pas la version d'OpenCV à partir des référentiels Ubuntu .
Mon module Python se compile sans problème et se charge correctement dans Python. Cependant, lorsque je compile ce module sur Ubuntu 11.10 ou 12.04, j'obtiens une ImportError avec le message "symbole non défini" lors de la tentative de chargement en Python.
Voici comment je compile le 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
Ceci est la sortie de "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
L'erreur que j'obtiens est:
ImportError: /path/to/service/mymodule.so: undefined symbol: _ZN5CvSVMD1Ev
Ma compréhension est que "symbole non défini" signifie généralement que le symbole donné ne peut être trouvé dans aucune des bibliothèques liées. Mais je sais que ce symbole est là dans libopencv_ml.so parce que quand je lance ceci:
$ nm -g /usr/local/lib/libopencv_ml.so | grep _ZN5CvSVMD1Ev
Je reçois:
000000000002fd40 T _ZN5CvSVMD1Ev
/ usr/local/lib semble être dans le cache de l'éditeur de liens dynamique.
$ cat /etc/ld.so.conf.d/libc.conf
# libc default configuration
/usr/local/lib
Et le fichier so est également présent dans le cache.
$ 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
Alors, pouvez-vous me donner une idée de ce que je pourrais faire de mal? Quelque chose a-t-il changé entre Ubuntu 11.04 et 11.10 dans la manière dont les bibliothèques partagées sont chargées lors de l'exécution de Python? Ou est-ce un problème avec OpenCV?
La solution consiste à placer le nom du module généré avant les autres modules dont il dépend, sur la ligne de commande 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
La page de manuel gcc dit de l'option "-l",
Cela fait une différence où, dans la commande, vous écrivez cette option; l'éditeur de liens recherche et traite les bibliothèques et les fichiers d'objets dans l'ordre où ils sont spécifiés. Ainsi, foo.o -lz bar.o recherche la bibliothèque z après le fichier foo.o mais avant bar.o. Si bar.o fait référence à des fonctions dans z, ces fonctions peuvent ne pas être chargées.
Étant donné que le nom de mymodule.so a été fourni avant les bibliothèques auxquelles il était censé être lié, aucun d'entre eux n'était réellement lié au fichier .so généré.
Merci pour @ J.F.Sebastian d'avoir souligné le fonctionnement de -l.