2010-08-03 6 views
2

J'ai une bibliothèque pour laquelle j'ai créé un wrapper python en utilisant SWIG. La bibliothèque elle-même accepte les fonctions fournies par l'utilisateur qui se trouvent dans un fichier .so lié dynamiquement. En ce moment je fais affaire avec un que j'ai moi-même créé et j'ai réussi à obtenir le lien dynamique travaillant ... en C++. Quand je tente de l'exécuter en python, j'obtiens des erreurs de symboles indéfinies. Ces symboles sont ceux qui ne sont pas présents dans le fichier .so fourni mais qui sont présents dans le programme principal (essentiellement, ce sont les fonctions qui permettent au module fourni d'accéder aux données du programme principal).Liaison dynamique et Python SWIG (C++) fonctionne en C++ échoue en python

Je ne reçois aucune erreur lors de l'exécution d'un programme de test court en C++, mais un programme de test court en python avec ce wrapper (qui fonctionnait précédemment) échoue. Je ne peux pas penser à une explication de pourquoi il échouerait en C++ et pas dans le python. Ce qui m'inquiète un peu, c'est l'idée que le C++ ne fonctionne pas correctement mais ne me le dit pas, et le python recueille des erreurs que le C++ ne fait pas. Pourtant, le résultat renvoyé par le C++ est précis, donc cela semble peu probable.

Des pensées comment cela est possible et donc comment je pourrais le réparer?

Merci.

Mise à jour: J'ai ajouté ce code au haut du programme:

import dl 
sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL) 

Cela se débarrasse de l'erreur d'exécution, mais permet malheureusement un deuxième problème se pose (toujours en raison de liens). Les fonctions appelées à partir de la bibliothèque liée dynamiquement qui font partie du programme principal ne retournent pas les valeurs correctes. Ils retournent 0. De plus, il est évident qu'ils ne sont même pas courus du tout. La question devient ce qui est en cours d'exécution, pourquoi est-il différent du C++, et comment puis-je résoudre ce problème?

Merci encore. Mise à jour: explication potentiellement plus claire Python importe un module, qui est ma bibliothèque C++ qui a été encapsulée par SWIG. Cette bibliothèque C++ utilise dlopen et dlsym pour obtenir des fonctions à partir d'un fichier .so fourni par l'utilisateur. L'utilisateur a fourni des appels de fichiers aux fonctions qui font partie de la bibliothèque C++ afin de faire son travail. Les appels de fonction du fichier .so à la bibliothèque C++ sont la partie qui échoue, c'est-à-dire qu'ils ne parviennent pas à appeler la fonction et retournent simplement 0. Cependant, cet échec se produit uniquement lorsque le code de test est écrit en python. Le code de test C++ qui utilise la bibliothèque fonctionne correctement.

+0

Je suis un peu clair sur la structure de votre code. Plus précisément, je suppose que le "programme principal" est en fait l'interpréteur Python (c'est-à-dire que vous ne l'incorporez pas) et que vous essayez de charger un .so qui était dynamiquement lié à un autre .so (à la compilation) pas chargé à la volée via dlopen()) mais c'est difficile à dire. Pourriez-vous être un peu plus précis sur ce que sont exactement les composants et comment ils sont reliés entre eux? – Rakis

+0

Désolé je ne voulais pas être clair! Python importe un module, qui est une bibliothèque C++ qui a été enveloppée par SWIG. Cette bibliothèque C++ utilise dlopen et dlsym pour obtenir des fonctions à partir d'un fichier .so fourni par l'utilisateur. L'utilisateur a fourni des appels de fichiers aux fonctions qui font partie de la bibliothèque C++ afin de faire son travail. La fonction appelle à partir du fichier .so à la bibliothèque C++ sont la partie qui échoue, c'est qu'ils ne parviennent pas à appeler la fonction et retourner simplement 0. Cependant cet échec ne se produit que lorsque le code de test est écrit en python. Le code de test C++ qui utilise la bibliothèque fonctionne correctement. – VolatileStorm

+1

Hmmm. C'est un scénario de liaison plutôt inhabituel. Il pourrait être utile d'essayer d'utiliser le module 'dl' pour charger explicitement votre .so fourni par l'utilisateur (assurez-vous d'avoir défini l'indicateur dl.RTLD_GLOBAL en premier). Cela devrait amener l'éditeur de liens à charger la bibliothèque C++ en tant que dépendance et, nous l'espérons, à veiller à ce que tous les symboles soient correctement pris en charge. Je n'aurais pas prévu d'avoir le problème que vous décrivez en premier lieu, alors je ne fais que deviner à ce stade. Tout ce que je peux dire avec certitude, c'est que la configuration de la liaison d'exécution est l'endroit où se trouve le problème. – Rakis

Répondre

2

Une solution est de faire en sorte que python est préchargement de la bibliothèque principale C de la portée mondiale. Ce n'est pas une solution très élégante, et je ne veux pas le faire, mais ça le fait fonctionner pour l'instant.

Après un peu farfouillé here et reconnaissant la variable d'environnement LD_LIBRARY_PATH que je dois mettre à chaque fois que je commence le terminal afin qu'il trouve même la principale bibliothèque C++ qui a été SWIGed, j'ai remarqué la variable d'environnement LD_PRELOAD. Lors de la définition du nom de fichier de la bibliothèque C++ principale, le programme a fonctionné.

Je suppose que c'est parce qu'il "peut être utilisé pour remplacer de manière sélective des fonctions dans d'autres bibliothèques partagées".

Si quelqu'un vient avec une meilleure réponse que la définition des variables d'environnement, il serait génial, comme je ne suis pas sûr que ce soit portable.

Edit: Le problème initial est que les fonctions que la bibliothèque fournie utilisateur est à la recherche ne sont pas dans la portée globale. Afin de résoudre ce problème en utilisant simplement "dl.open" de python pour ouvrir le fichier .so de la bibliothèque principale, en utilisant dl.RTLD_NOW et dl.RTLD_GLOBAL.

succès!

1

L'interpréteur python charge probablement votre wrapper .so sans mettre ses symboles à la disposition d'autres bibliothèques de liens dynamiques (pour éviter les conflits de symboles). Essayez d'ajouter les lignes suivantes juste avant d'importer votre emballage:

import dl 
sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL) 
+0

Merci, cela fonctionne pour se débarrasser de l'erreur d'exécution, mais malheureusement, il provoque une autre erreur. Le code ne fonctionne pas correctement maintenant et après un peu de débogage, il se trouve que les fonctions du programme principal que le fichier .so tente d'appeler ne sont pas réellement appelés. Changer les valeurs de retour ou même y placer une sortie de console ne fait aucune différence. Ils retournent simplement 0. Aide! – VolatileStorm