La puissance de Pybind11 est capturée par la citation suivante de la lecture de Pybind11:
Pybind11 est une bibliothèque d'en-tête légère unique qui expose les types C ++ dans Python et vice versa, principalement pour créer des liaisons Python du code C ++ existant. Ses objectifs et sa syntaxe sont similaires à l'excellente bibliothèque Boost.python de David Abrahams ...
Le principal problème avec boost.python - et la raison de la création d'un projet aussi similaire - est Boost. Boost est une suite de bibliothèques d'utilité extrêmement grande et complexe qui fonctionne avec presque tous les compilateurs C ++ existants. ... Maintenant que les compilateurs compatibles C ++ 11 sont largement disponibles, cette machinerie lourde est devenue une dépendance excessivement grande et inutile.
Ce référentiel contient plusieurs exemples pour l'utilisation de Pybind11. Même si la documentation en ligne fournie par les développeurs de PYBIND11 rend l'utilisation relativement simple, plusieurs exemples - tels que fournis ici - rendent Pybind11 encore plus facile à utiliser. Ces exemples sont destinés à démarrer plus rapidement avec Pybind11. Ils ne sont cependant en aucun cas exhaustifs et ne fournissent pas toujours le choix optimal. Par conséquent, il est très conseillé de penser par vous-même . De plus, les contributions avec des exemples simples similaires (ou en améliorant davantage des exemples existants) sont très bienvenues . Veuillez déposer une demande de traction ou un problème sur GitHub, ou contactez-moi.
Pour donner un crédit là où le crédit est dû:
Les créateurs de Pybind11 ont fait un excellent travail! Il est vraiment facile à utiliser et très léger. La documentation est également déjà assez complète.
Les exemples mis à disposition par Cliburn Chan et Janice McCarthy, à l'Université Duke ont été d'une aide énorme. Veuillez également lire leur documentation.
Notez qu'il existe également des cas de test qui doublent comme exemples dans le référentiel PYBIND11, mais ceux-ci ne sont pas très perspicaces lorsque vous êtes nouveau dans PYBIND11.
Enfin, Pybind11 est activement utilisé. On peut donc regarder dans les bibliothèques activement entretenues pour des solutions spécifiques. Par exemple:
Le module Pybind11 (qui est uniquement!) Est inclus comme sous-module de ce référentiel. Cela nécessite une certaine attention lors du clonage de ce projet. Il y a deux options:
L'option la plus simple est:
git clone --recursive https://github.com/tdegeus/pybind11_examples.gitCela téléchargera le sous-module jusqu'à la version utilisée dans ce projet. Pour mettre à jour le dernier engagement du sous-module lui-même:
git submodule update --remoteOn pourrait également télécharger directement le sous-module à partir de la source:
git clone https://github.com/tdegeus/pybind11_examples.git
cd pybind11_examples
git submodule init
git submodule updateLa bibliothèque Eigen est utilisée dans certains des exemples Numpy. À partir de ces exemples, il peut être observé que via Pybind11, Eigen et Numpy sont vraiment des modules de poignée de main. Presque aucun code n'est nécessaire pour créer l'interface C ++ / Python. Notez que la majeure partie de la simplicité dépend des copies passées, une certaine attention est nécessaire si l'on veut passer uniquement par référence.
Eigen n'a pas besoin d'installation car il est également en tête uniquement. Il suffit de télécharger les fichiers et d'inclure les en-têtes au moment de la compilation.
En général, on peut télécharger et installer Eigen par:
mkdir /path/to/temp/build
cmake /path/to/eigen/download
make installPour macOS, on pourrait simplement utiliser
brew install eigen
Par la suite compiler avec
clang++ -I/path/to/eigen/instalation ...Notez que, lorsqu'il est correctement configuré (ce qui est normalement le cas), PKG-Config peut être utilisé pour garder une trace des chemins:
clang++ ` pkg-config --cflags eigen3 ` ...Ou on peut utiliser cmake (voir ci-dessous).
Si vous avez une bibliothèque simple, vous voudrez peut-être tout faire vous-même. Dans ce cas, vous compilez votre source C ++ à un objet partagé qui est lié à Python. Cela se résume à
c++ -O3 -shared -std=gnu++11 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPIC Les applications PYBIND11 peuvent être compilées très faciles à l'aide de CMake. Pour la simplicité, Pybind11 est inclus en tant que sous-dossier des exemples ci-dessous (en fait en utilisant un lien symbolique à de nombreux exemplaires), afin que nous puissions utiliser un CMakeLists.txt comme:
cmake_minimum_required ( VERSION 2.8.12)
project (example)
add_subdirectory (pybind11)
pybind11_add_module(example example.cpp) (où cet exemple de module se compose d'un seul fichier source example.cpp ). Pour le compiler, utilisez:
cd /path/to/build
cmake /path/to/example/src
make Lorsque Eigen est «installé», il peut être facilement inclus en ajoutant ce qui suit dans CMakeLists.txt :
find_package ( PkgConfig )
pkg_check_modules( EIGEN3 REQUIRED eigen3 )
include_directories ( ${EIGEN3_INCLUDE_DIRS} ) La norme C ++ 14 peut être utilisée en incluant les éléments suivants dans CMakeLists.txt :
set (CMAKE_CXX_STANDARD 14) Un fichier setup.py peut être ajouté à votre bibliothèque. Vous pouvez ensuite compiler et installer en utilisant
python3 setup.py build
python3 setup.py install Bien que l'écriture de setup.py ne soit pas difficile, elle n'est pas couverte ici. On peut utiliser certains outils inclus dans CPPMAT, qui peuvent être installés avec PIP (par exemple pip3 install cppmat ). De plus, on peut consulter la setup.py de par exemple goosetenser ou plusieurs autres de mes référentiels.
Cet exemple dispose d'une fonction modify qui prend une liste (en lecture seule), multiplie toutes les entrées par deux et la renvoie comme une liste de doubles (voir example.cpp ). De Python, cette fonction est contenue dans un example de module simple (voir test.py ).
Le but de cet exemple est de montrer comment faire en sorte qu'une fonction accepte une liste, comment convertir cela en std::vector et comment renvoyer un nouveau std::vector (ou liste). Notez que l'opération réelle n'est pas très importante, c'est l'interface qui est illustrée.
Pour compiler, soit employer CMake, par lequel les instructions de compilation sont lues dans CMakeLists.txt par la suite:
cmake .
makeOu compilez directement en utilisant:
c++ -O3 -shared -std=gnu++11 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPICExécutez l'exemple par:
python3 test.pyPour fonctionner avec Python 2, remplacez simplement les deux occurrences de "Python3" ci-dessus par "Python". Pour modifier les instructions CMake, trouver plus en ligne.
Identique à l'exemple précédent, mais avec une liste imbriquée.
Une fonction modify qui convertit les entrées d'un tableau unidimensionnel en entiers, puis multiplie ces entrées par 10.
Le but de cet exemple est de montrer comment faire en sorte qu'une fonction accepte un tableau Numpy unidimensionnel, comment convertir cela en std::vector et comment renvoyer un réseau Numpy unidimensionnel. Notez que l'interface générée à l'aide de Pybind11 est si flexible qu'elle accepte même les entrées de liste du côté Python.
Une length de fonction. Cette fonction accepte une «matrice» dans laquelle comprend une liste de vecteurs de position 2D, comme des lignes. Le résultat est à nouveau une 'matrice' avec pour chaque ligne la position "x" et "y" et la longueur du vecteur de position 2D.
Deux fonctions det et inv qui utilisent la bibliothèque Eigen.
Le but de cet exemple est de montrer à quel point l'interaction entre C ++ / Eigen et Python / Numpy est.
Pour compiler à l'aide de CMake et pour fonctionner, suivez les instructions ci-dessus (où les en-têtes propres sont inclus dans CMakeLists.txt . Pour compiler directement, les en-têtes propres doivent être inclus:
c++ -O3 -shared -std=gnu++11 -I /path/to/eigen -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPICPar exemple sur macOS avec homebrew:
c++ -O3 -shared -std=gnu++11 -I /usr/local/Cellar/eigen/3.3.1/include/eigen3 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPIC Une classe CustomVectorXd personnalisée avec une fonction mul . Cette classe utilise la bibliothèque Eigen. Il comprend également un argument par défaut.
En outre, cet exemple a une fonction trans (totalement sans rapport avec la classe CustomVectorXd personnalisée). Son but est de montrer comment retourner une nouvelle Eigen::VectorXi (ou Numpy-array).
Une fonction surchargée mul . Cette fonction agit «différemment» si elle est appelée avec des arguments int ou des arguments double . Notez que le comportement par défaut de Pybind11 est assez robuste. Lorsque vous appelez la fonction avec un argument int et un double , le module choisira la version double de mul (et jettera l'argument int en double ).
Pour compiler, assurez-vous que la norme C ++ 14 est utilisée, par exemple en incluant -std=c++14 comme argument du compilateur.
Semblable à l'exemple précédent, mais avec des arguments propres (c'est-à-dire des arguments numpy du côté python).
Pour compiler, assurez-vous que la norme C ++ 14 est utilisée.
Cet exemple comprend une classe de matrice personnalisée en C ++ (dans matrix.h ). Cette classe est couplée à une arrayage Numpy en utilisant une interface simple (dans pybind_matrix.h ). Par conséquent, les fonctions (dans example.cpp ) ne nécessitent aucun code de wrapper spécial.
Voir aussi cette discussion sur le débordement de la pile.
Cet exemple présente un moyen d'interfacer avec un énumérateur en C ++. En principe, l'interface est simple mais justifie une «astuce». Ici, un sous-module est utilisé pour interagir avec l'énumérateur de la même manière que dans C ++.
Cet exemple contient un exemple classique où une ou plusieurs classes sont dérivées d'un certain parent ou d'un certain modèle. Cet exemple particulier contient deux animaux, un Dog et un Cat , qui sont tous deux dérivés d'une classe Animal générique. Il y a un talk en fonction qui accepte l' Animal générique et donc l'une des classes dérivées.
Ce cas particulier nécessite une interface plus impliquée, comme décrit dans la documentation.
Cet exemple présente un CRTP simple avec As «Base» et une classe «dérivée», et son enregistrement à l'API Pybind11 .
Parfois, py::overload_cast n'est pas en mesure de résoudre votre fonction, par exemple lorsque le type de retour ne peut pas être déduit. Dans ce cas, vous pouvez être explicite par static_cast ing un pointeur vers votre fonction, plus d'informations peuvent être trouvées dans la documentation.