2011-01-05 3 views
1

Ceci est une question noob. J'essaie d'apprendre à utiliser SWIG pour créer une interface python pour une bibliothèque C++. La bibliothèque est une bibliothèque tierce propriétaire; il me vient sous la forme d'un fichier d'en-tête (foo.h) et d'une archive statique (libfoo.a). Pour simplifier, j'ai inventé un exemple qui, je pense, a la même pathologie. Même message d'erreur de toute façon.Compiler un wrapper Python SWIG pour une bibliothèque statique?

/* foo.hpp */ 
class TC { 
    public: 
     TC(); 
     int i; 
    private: 
}; 

Pour référence, voici foo.c. Je n'ai que l'en-tête et les fichiers d'archive pour la vraie bibliothèque tierce.

/*foo.cxx */ 
#include "foo.hpp" 
TC::TC() { 
    i = 0; 
} 

J'ai fait cette bibliothèque en tapant g++ -c foo.cxx && ar rcs libfoo.a foo.o

Mon fichier d'interface SWIG est comme suit:

/* foo.i */ 
%module foo 
%{ 
#include "foo.hpp" 
%} 
%include "foo.hpp" 

je produis foo_wrap.cxx en tapant

swig -python -c++ foo.i 

puis compiler .

g++ -c -fPIC -I/usr/include/python2.6 foo_wrap.cxx 
g++ -shared -L. -lfoo -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -o _foo.so 

La compilation réussit, mais quand je lance Python et import foo, je reçois une erreur de symbole non défini.

>>> import foo 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
    File "foo.py", line 25, in <module> 
    _foo = swig_import_helper() 
    File "foo.py", line 21, in swig_import_helper 
    _mod = imp.load_module('_foo', fp, pathname, description) 
ImportError: ./_foo.so: undefined symbol: _ZN2TCC1Ev 

Que se passe-t-il ici? Le problème semble être que l'étape de liaison ne trouve pas la définition du constructeur TC :: TC.

Note: Si je modifie l'étape de liaison à

g++ -shared -L. -lfoo -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -o _foo.so 

alors tout fonctionne. Mais est-ce une option pour mon vrai problème, où je n'ai pas le code source brut? Peut-on extraire un .o d'un .a? Vraisemblablement, on peut le faire à la main, mais ne devrait-il pas y avoir une façon automatisée de le faire?

Répondre

6

Je ne suis pas vraiment sûr que ce soit le cas pour vous mais en général l'ordre des fichiers objets et des bibliothèques statiques est important. L'ordre définit l'ordre d'initialisation.

Vous devez placer les objets les plus généraux et/ou les archives statiques comme derniers paramètres. Les objets/archives avec le plus de dépendances doivent être placés au début.

Un exemple. Le fichier objet A.o offre la fonction A(). L'objet B.o utilise la fonction A(). Vous devez écrire ld -o libmy.so B.o A.o (le fichier le plus général A.o comme dernier paramètre).

Vous pouvez également vérifier avec objdump -x _foo.so si le symbole existe dans le fichier.

L'appel droit serait: g++ -shared -L. -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -lfoo -o _foo.so

Ne pas confondre avec -lpython2.6, il est une bibliothèque dynamique liée àexécution.

+0

Ce commentaire était éducatif, et semble avoir résolu mon problème. Je vous remercie! Malheureusement, je n'ai pas assez de réputation pour upvote. – user1504

+0

En acceptant votre réponse, j'ai assez de rep pour vous donner un vote! – user1504

Questions connexes