Quelle serait la manière la plus rapide de construire une liaison Python à une bibliothèque C ou C ++?
(J'utilise Windows si cela est important.)
Vous devriez jeter un œil à Boost.Python . Voici la courte introduction tirée de leur site Web:
La bibliothèque Boost Python est un cadre pour interfacer Python et C ++. Il vous permet d'exposer rapidement et de manière transparente des fonctions et des objets de classes C ++ à Python, et vice-versa, sans utiliser d'outils spéciaux - juste votre compilateur C ++. Il est conçu pour encapsuler les interfaces C ++ de manière non intrusive, de sorte que vous ne devriez pas avoir à modifier du tout le code C ++ afin de l'encapsuler, ce qui rend Boost.Python idéal pour exposer des bibliothèques tierces à Python. L'utilisation par la bibliothèque de techniques avancées de métaprogrammation simplifie sa syntaxe pour les utilisateurs, de sorte que le code d'habillage prend l'apparence d'une sorte de langage de définition d'interface déclarative (IDL).
Le module ctypes fait partie de la bibliothèque standard et est donc plus stable et largement disponible que swig , ce qui a toujours eu tendance à me poser des problèmes .
Avec les ctypes, vous devez satisfaire toute dépendance de temps de compilation sur python, et votre liaison fonctionnera sur n'importe quel python qui a des ctypes, pas seulement celui avec lequel il a été compilé.
Supposons que vous ayez un exemple de classe C ++ simple dans lequel vous souhaitez parler dans un fichier appelé foo.cpp:
Comme les ctypes ne peuvent parler qu'aux fonctions C, vous devez fournir ceux qui les déclarent comme "C" externe
Ensuite, vous devez compiler cela dans une bibliothèque partagée
Et enfin, vous devez écrire votre wrapper python (par exemple dans fooWrapper.py)
Une fois que vous l'avez, vous pouvez l'appeler comme
la source
extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Foo_delete
fonction et en l'appelant depuis un destructeur python ou en enveloppant l'objet dans une ressource .La façon la plus rapide de le faire est d'utiliser SWIG .
Exemple du didacticiel SWIG :
Fichier d'interface:
Construire un module Python sous Unix:
Usage:
Notez que vous devez avoir python-dev. Dans certains systèmes, les fichiers d'en-tête python seront également dans /usr/include/python2.7 en fonction de la façon dont vous l'avez installé.
Du tutoriel:
la source
J'ai commencé mon voyage dans la liaison Python <-> C ++ à partir de cette page, dans le but de lier des types de données de haut niveau (vecteurs STL multidimensionnels avec des listes Python) :-)
Ayant essayé les solutions basées à la fois sur ctypes et boost.python (et n'étant pas ingénieur logiciel), je les ai trouvées complexes lorsqu'une liaison de types de données de haut niveau est requise, alors que j'ai trouvé SWIG beaucoup plus simple pour de tels cas.
Cet exemple utilise donc SWIG, et il a été testé sous Linux (mais SWIG est disponible et est également largement utilisé sous Windows).
L'objectif est de mettre à la disposition de Python une fonction C ++ qui prend une matrice sous la forme d'un vecteur STL 2D et renvoie une moyenne de chaque ligne (en tant que vecteur STL 1D).
Le code en C ++ ("code.cpp") est le suivant:
L'en-tête équivalent ("code.h") est:
Nous compilons d'abord le code C ++ pour créer un fichier objet:
Nous définissons ensuite un fichier de définition d'interface SWIG ("code.i") pour nos fonctions C ++.
À l'aide de SWIG, nous générons un code source d'interface C ++ à partir du fichier de définition d'interface SWIG.
Nous compilons enfin le fichier source de l'interface C ++ généré et lions tout ensemble pour générer une bibliothèque partagée directement importable par Python (le "_" compte):
Nous pouvons maintenant utiliser la fonction dans les scripts Python:
la source
Il y a aussi
pybind11
, qui est comme une version allégée de Boost.Python et compatible avec tous les compilateurs C ++ modernes:https://pybind11.readthedocs.io/en/latest/
la source
Pytorch
pytorch.org/tutorials/advanced/cpp_extension.html Fonctionne également entièrement surVS Community
WindowsCheck-out pyrex ou Cython . Ce sont des langages de type Python pour l'interfaçage entre C / C ++ et Python.
la source
Pour le C ++ moderne, utilisez cppyy: http://cppyy.readthedocs.io/en/latest/
Il est basé sur Cling, l'interpréteur C ++ pour Clang / LLVM. Les liaisons sont au moment de l'exécution et aucun langage intermédiaire supplémentaire n'est nécessaire. Grâce à Clang, il prend en charge C ++ 17.
Installez-le en utilisant pip:
Pour les petits projets, chargez simplement la bibliothèque appropriée et les en-têtes qui vous intéressent. Par exemple, prenez le code de l'exemple ctypes est ce fil, mais divisé en sections d'en-tête et de code:
Compilez-le:
et l'utiliser:
Les grands projets sont pris en charge avec le chargement automatique des informations de réflexion préparées et les fragments cmake pour les créer, afin que les utilisateurs des packages installés puissent simplement exécuter:
Grâce à LLVM, des fonctionnalités avancées sont possibles, telles que l'instanciation automatique des modèles. Pour continuer l'exemple:
Remarque: je suis l'auteur de cppyy.
la source
swig
,ctypes
ouboost.python
. Au lieu d'avoir à écrire du code pour que python fonctionne avec votre code c ++ ... python fait le travail difficile pour comprendre c ++. En supposant que cela fonctionne réellement.Cet article, affirmant que Python est tout ce dont un scientifique a besoin , dit essentiellement: Tout d'abord prototype de tout en Python. Ensuite, lorsque vous devez accélérer une partie, utilisez SWIG et traduisez cette partie en C.
la source
Je ne l'ai jamais utilisé mais j'ai entendu de bonnes choses sur les types de c . Si vous essayez de l'utiliser avec C ++, assurez-vous d'éviter le changement de nom via
extern "C"
. Merci pour le commentaire, Florian Bösch.la source
Je pense que cffi pour python peut être une option.
http://cffi.readthedocs.org/en/release-0.7/
la source
La question est de savoir comment appeler une fonction C à partir de Python, si j'ai bien compris. Ensuite, le meilleur pari est Ctypes (BTW portable sur toutes les variantes de Python).
Pour un guide détaillé, vous pouvez vous référer à mon article de blog .
la source
L'un des documents officiels Python contient des détails sur l' extension de Python à l'aide de C / C ++ . Même sans l'utilisation de SWIG , c'est assez simple et fonctionne parfaitement bien sous Windows.
la source
Cython est certainement la voie à suivre, sauf si vous prévoyez d'écrire des wrappers Java, auquel cas SWIG peut être préférable.
Je recommande d'utiliser l'
runcython
utilitaire de ligne de commande, cela rend le processus d'utilisation de Cython extrêmement simple. Si vous devez transmettre des données structurées à C ++, jetez un œil à la bibliothèque de protobuf de Google, c'est très pratique.Voici quelques exemples minimes que j'ai faits qui utilisent les deux outils:
https://github.com/nicodjimenez/python2cpp
J'espère que cela peut être un point de départ utile.
la source
Vous devez d'abord décider quel est votre objectif particulier. La documentation officielle de Python sur l' extension et l'incorporation de l'interpréteur Python a été mentionnée ci-dessus, je peux ajouter un bon aperçu des extensions binaires . Les cas d'utilisation peuvent être divisés en 3 catégories:
Afin de donner une perspective plus large aux autres personnes intéressées et puisque votre question initiale est un peu vague ("à une bibliothèque C ou C ++"), je pense que cette information pourrait vous intéresser. Sur le lien ci-dessus, vous pouvez lire les inconvénients de l'utilisation des extensions binaires et de ses alternatives.
Outre les autres réponses suggérées, si vous voulez un module accélérateur, vous pouvez essayer Numba . Il fonctionne "en générant du code machine optimisé à l'aide de l'infrastructure du compilateur LLVM au moment de l'importation, de l'exécution ou de façon statique (à l'aide de l'outil pycc inclus)".
la source
J'adore cppyy, il est très facile d'étendre Python avec du code C ++, augmentant considérablement les performances en cas de besoin.
Il est puissant et franchement très simple à utiliser,
ici, c'est un exemple de la façon dont vous pouvez créer un tableau numpy et le passer à une fonction membre de classe en C ++.
cppyy_test.py
Buffer.h
Vous pouvez également créer un module Python très facilement (avec CMake), de cette façon vous éviterez de recompiler le code C ++ tout le temps.
la source
exemple exécutable minimal pybind11
pybind11 a déjà été mentionné sur https://stackoverflow.com/a/38542539/895245 mais je voudrais donner ici un exemple d'utilisation concret et quelques discussions supplémentaires sur la mise en œuvre.
Dans l'ensemble, je recommande fortement pybind11 car il est vraiment facile à utiliser: vous incluez simplement un en-tête, puis pybind11 utilise la magie des modèles pour inspecter la classe C ++ que vous souhaitez exposer à Python et le fait de manière transparente.
L'inconvénient de ce modèle magique est qu'il ralentit la compilation en ajoutant immédiatement quelques secondes à tout fichier utilisant pybind11, voir par exemple l'enquête effectuée sur ce problème . PyTorch est d'accord .
Voici un exemple exécutable minimal pour vous donner une idée de la qualité de pybind11:
class_test.cpp
class_test_main.py
Compiler et exécuter:
Cet exemple montre comment pybind11 vous permet d'exposer sans effort la
ClassTest
classe C ++ à Python! La compilation produit un fichier nomméclass_test.cpython-36m-x86_64-linux-gnu.so
quiclass_test_main.py
prend automatiquement le point de définition duclass_test
module défini nativement.Peut-être que la réalisation de la façon dont c'est génial ne s'enfonce que si vous essayez de faire la même chose à la main avec l'API Python native, voir par exemple cet exemple de faire cela, qui a environ 10 fois plus de code: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c Sur cet exemple, vous pouvez voir comment le code C doit définir douloureusement et explicitement la classe Python bit par bit avec toutes les informations qu'il contient (membres, méthodes, plus loin) métadonnées ...). Voir également:
pybind11 prétend être similaire à
Boost.Python
ce qui a été mentionné sur https://stackoverflow.com/a/145436/895245 mais plus minimal car il est libéré du ballonnement d'être à l'intérieur du projet Boost:pybind11 est également la seule alternative non native mise en évidence par la documentation de liaison Microsoft Python C actuelle sur: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- visual-studio? view = vs-2019 ( archive ).
Testé sur Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.
la source