Question

En python, dans quelles circonstances SWIG est-il un meilleur choix que les types de type pour appeler des points d’entrée dans des bibliothèques partagées? Supposons que vous ne possédez pas déjà le (s) fichier (s) d'interface SWIG.

Quelles sont les mesures de performance des deux?

Était-ce utile?

La solution

SWIG génère du code C ou C ++ (plutôt moche). Il est simple à utiliser pour des fonctions simples (éléments pouvant être traduits directement) et relativement facile à utiliser pour des fonctions plus complexes (telles que des fonctions avec des paramètres de sortie nécessitant une étape de traduction supplémentaire à représenter en Python). besoin d'écrire des bits de C dans le fichier d'interface. Pour une utilisation autre que simple, vous devez connaître CPython et sa façon de représenter les objets - pas difficile, mais quelque chose à garder à l'esprit.

ctypes vous permet d'accéder directement aux fonctions, structures et autres données C, et de charger des bibliothèques partagées arbitraires. Vous n'avez pas besoin d'écrire de C pour cela, mais vous devez comprendre comment fonctionne C. On peut dire que c’est le revers de SWIG: il ne génère pas de code et ne nécessite pas de compilateur au moment de l’exécution, mais pour une utilisation autre que simple, il nécessite que vous compreniez comment des choses comme les types de données C, la conversion, gestion de la mémoire et travail d'alignement. Vous devez également traduire manuellement ou automatiquement les structures, les unions et les tableaux en C dans la structure de données ctypes équivalente, y compris la structure de mémoire appropriée.

Il est probable qu'en exécution pure, SWIG soit plus rapide que les ctypes, car la gestion du travail réel est effectuée en C au moment de la compilation plutôt qu'en Python au moment de l'exécution. Cependant, à moins d’interfacer de nombreuses fonctions C différentes, mais qu’elles ne le soient que quelques fois, il est peu probable que la surcharge soit vraiment perceptible.

En temps de développement, ctypes a un coût de démarrage beaucoup plus bas: vous n'avez pas à apprendre les fichiers d'interface, vous n'avez pas besoin de générer de fichiers .c et de les compiler, vous n'avez pas besoin de vérifier et de couper avertissements. Vous pouvez simplement vous lancer et commencer à utiliser une seule fonction C avec un minimum d'effort, puis l'étendre à davantage. Et vous pouvez tester et essayer des choses directement dans l'interpréteur Python. Il est assez fastidieux d’emballer du code, même s’il est tenté de simplifier les choses (comme ctypes-configure.)

SWIG, d’autre part, peut être utilisé pour générer des wrappers pour plusieurs langues (sauf les détails spécifiques à une langue qui doivent être complétés, comme le code C personnalisé que j'ai mentionné ci-dessus.) Lors du wrapping de beaucoup de codes que SWIG peut manipuler avec peu d’aide, la génération de code peut aussi être beaucoup plus simple à configurer que les équivalents ctypes.

Autres conseils

J'ai une riche expérience d'utilisation de swig. SWIG affirme qu'il s'agit d'une solution rapide pour emballer des objets. Mais dans la vraie vie ...

Inconvénients:

SWIG est conçu pour être général, pour tout le monde et pour plus de 20 langues. Généralement, cela entraîne des inconvénients:
- nécessite une configuration (modèles SWIG .i), parfois délicate,
- absence de traitement de certains cas particuliers (voir propriétés de python plus loin),
- manque de performance pour certaines langues.

Contre Python:

1) Incohérence dans le style du code . C ++ et Python ont des styles de code très différents (ce qui est évident, certainement), les possibilités de swig de rendre le code cible plus Pythonish sont très limitées. Par exemple, il est difficile de créer des propriétés à partir de getters et de setters. Voir ce q & amp .

2) Manque de communauté large . SWIG a une bonne documentation. Mais si quelqu'un attrape quelque chose qui ne figure pas dans la documentation, il n'y a aucune information. Pas de blogs, ni googler aide. Il faut donc beaucoup creuser le code généré par SWIG dans de tels cas ... C’est terrible, je pourrais dire ...

Avantages:

  • Dans les cas simples, il est très rapide, facile et direct

  • Si vous avez généré une fois des fichiers d'interface swig, vous pouvez envelopper ce code C ++ dans N'IMPORTE QUELLE AUTRES langues (plus de 20) (!!!).

  • Une des grandes préoccupations de SWIG est sa performance. Depuis la version 2.04, SWIG inclut l'indicateur "-builtin" qui rend SWIG encore plus rapide que d'autres méthodes de wrapping automatisées. Au moins quelques points de repère le montrent bien.

Quand utiliser SWIG?

J'ai donc conclu moi-même à deux cas où l'utilisation de swig est bonne:

2) S'il est nécessaire d'encapsuler le code C ++ pour plusieurs langues . Ou si, potentiellement, il pourrait y avoir un moment où il faudrait distribuer le code pour plusieurs langues. L'utilisation de SWIG est fiable dans ce cas.

1) Si vous devez rapidement encapsuler seulement plusieurs fonctions d'une bibliothèque C ++ pour une utilisation finale.

Expérience en direct

Mettre à jour :
Cela fait un an et demi que nous avons converti notre bibliothèque en utilisant SWIG.

Tout d'abord, nous avons créé une version en python. Il y a eu plusieurs moments où nous avons eu des problèmes avec SWIG - c'est vrai. Mais pour le moment, nous avons étendu notre bibliothèque à Java et .NET. Nous avons donc 3 langues avec 1 SWIG. Et je pourrais dire que le SWIG bascule en termes de gain de temps.

Mise à jour 2 :
Cela fait deux ans que nous utilisons SWIG pour cette bibliothèque. SWIG est intégré à notre système de construction. Récemment, nous avons eu un changement majeur d'API de la bibliothèque C ++. SWIG a parfaitement fonctionné. La seule chose à faire est d’ajouter plusieurs fichiers% rename aux noms de fichiers .i afin que notre CppCamelStyleFunctions () maintenant looks_more_pythonish en python. Premièrement, je craignais que certains problèmes ne se posent, mais rien ne s'est mal passé. C'était incroyable. Juste plusieurs éditions et tout distribué en 3 langues. Maintenant, je suis convaincu que c’était une bonne solution d’utiliser SWIG dans notre cas.

Mise à jour 3 :
Cela fait plus de 3 ans que nous utilisons SWIG pour notre bibliothèque. Changement majeur : la partie python a été totalement réécrite en python pur. La raison en est que Python est utilisé pour la majorité des applications de notre bibliothèque. Même si la version Python pur fonctionne plus lentement que le wrapping C ++, il est plus pratique pour les utilisateurs de travailler avec Python pur et non avec des bibliothèques natives.

SWIG est toujours utilisé pour les versions .NET et Java.

La question principale ici "Aurions-nous recours à SWIG pour python si nous avions démarré le projet depuis le début?". Nous serions! SWIG nous a permis de distribuer rapidement notre produit dans de nombreuses langues. Cela a fonctionné pendant une période qui nous a permis de mieux comprendre les besoins de nos utilisateurs.

CTypes est très cool et beaucoup plus facile que SWIG, mais il présente l’inconvénient que le code python mal écrit ou mal écrit peut en réalité faire planter le processus python. Vous devez également envisager de booster . IMHO c'est en fait plus facile que swig tout en vous donnant plus de contrôle sur l'interface finale de python. De toute façon, si vous utilisez C ++, vous n’ajoutez pas d’autres langues à votre mixage.

D'après mon expérience, ctypes a un gros inconvénient: quand quelque chose ne va pas (et cela se produira invariablement pour toutes les interfaces complexes), c'est un enfer à déboguer.

Le problème est qu’une grande partie de votre pile est obscurcie par la magie ctypes / ffi et qu’il n’ya pas de moyen facile de déterminer comment vous êtes arrivé à un point particulier et pourquoi les valeurs de paramètre sont ce qu’elles sont.

Vous pouvez également utiliser Pyrex , qui peut agissent comme un liant entre le code Python de haut niveau et le code C de bas niveau. Le lxml est écrit en Pyrex, par exemple.

Je vais être à contre-courant et suggérer que, si vous le pouvez, vous devriez écrire votre bibliothèque d’extensions à l’aide de API Python standard . Il est vraiment bien intégré des points de vue C et Python ... si vous avez une expérience de l’API Perl, vous y trouverez une très agréable surprise.

Ctypes, c’est bien aussi, mais comme d’autres l’ont dit, C ++ n’est pas utilisé.

Quelle est la taille de la bibliothèque que vous essayez de boucler? Combien de temps la base de code change-t-elle? Avez-vous d'autres problèmes de maintenance? Tout cela affectera probablement le choix du meilleur moyen d'écrire les liaisons Python.

ctypes est excellent, mais ne gère pas les classes C ++. J'ai également constaté que ctypes est environ 10% plus lent qu'une liaison directe en C, mais cela dépendra beaucoup de ce que vous appelez.

Si vous envisagez d'utiliser des ctypes, vérifiez les projets Pyglet et Pyopengl, qui proposent de nombreux exemples de liaisons de type ctype.

Je voulais juste ajouter quelques considérations supplémentaires que je n'ai pas encore vu mentionnées. [EDIT: Ooops, n'a pas vu la réponse de Mike Steder]

Si vous souhaitez utiliser une implémentation non Cpython (telle que PyPy, IronPython ou Jython), ctypes est à peu près la seule solution. PyPy n'autorise pas l'écriture d'extensions C, ce qui exclut pyrex / cython et Boost.python. Pour la même raison, ctypes est le seul mécanisme qui fonctionnera pour IronPython et (éventuellement, une fois qu'ils fonctionneront) jython.

Comme l’a mentionné une autre personne, aucune compilation n’est requise. Cela signifie que si une nouvelle version du fichier .dll ou .so est disponible, vous pouvez simplement la déposer et charger cette nouvelle version. Tant qu'aucune des interfaces n'a changé, le remplacement est insuffisant.

Il convient de garder à l’esprit que SWIG ne cible que l’implémentation CPython. Puisque ctypes est également supporté par les implémentations PyPy et IronPython, il peut être intéressant d’écrire vos modules avec ctypes pour assurer la compatibilité avec l’écosystème Python au sens large.

J’ai trouvé SWIG un peu trop lourd dans son approche (en général, pas seulement en Python) et difficile à mettre en œuvre sans devoir franchir le point douloureux d’écrire du code Python avec un état d’esprit explicite pour être favorable à SWIG, plutôt que écrire du code Python propre et bien écrit. C'est, IMHO, un processus beaucoup plus simple d'écrire des liaisons C en C ++ (si vous utilisez C ++), puis d'utiliser ctypes pour l'interface avec n'importe quelle couche C.

Si la bibliothèque avec laquelle vous vous connectez a une interface C dans le cadre de la bibliothèque, un autre avantage des ctypes est qu'il n'est pas nécessaire de compiler une bibliothèque distincte de liaisons python pour accéder aux bibliothèques tierces. Cela est particulièrement intéressant pour la formulation d’une solution pure-python qui évite les problèmes de compilation entre plates-formes (pour les bibliothèques tierces proposées sur des plates-formes disparates). Avoir à intégrer le code compilé dans un paquet que vous souhaitez déployer sur quelque chose comme PyPi de manière conviviale sur plusieurs plates-formes est une tâche ardue; L'un de mes points les plus irritants sur les paquets Python utilisant SWIG ou le code C explicite sous-jacent est leur indisponibilité générale multiplate-forme. Considérez donc ceci si vous travaillez avec des bibliothèques tierces disponibles multiplates-formes et que vous développez une solution python autour d’elles.

En tant qu'exemple concret, considérons PyGTK. Ceci (je crois) utilise SWIG pour générer du code C afin de s’interfacer avec les appels GTK C. Je ne l'ai utilisé que très peu de temps pour trouver qu'il était très difficile à configurer et à utiliser, avec des erreurs bizarres si vous ne faites pas les choses dans le bon ordre lors de la configuration et en général. C'était une expérience tellement frustrante et lorsque j'ai jeté un œil aux définitions d'interface fournies par GTK sur le Web, j'ai compris à quel point ce serait un exercice simple d'écrire un traducteur de ces interfaces en python ctypes. Un projet appelé PyGGI était né, et en UN jour, j'ai pu réécrire PyGTK pour en faire un produit beaucoup plus fonctionnel et utile, parfaitement adapté aux interfaces GTK orientées objet. Et cela n’a nécessité aucune compilation de code C, ce qui le rend convivial pour toutes les plateformes. (J'étais en fait après avoir interfacé avec webkitgtk, qui n'est pas si multi-plateforme). Je peux aussi facilement déployer PyGGI sur n’importe quelle plate-forme supportant GTK.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top