Utilisation des fonctions C ++ de python avec pybind11

Cet article

Calendrier de l'Avent Python 2016 C'est le 8ème jour.

J'ai parlé de pybind11 lors de la session d'étude de Boost de cette année, mais je n'ai pas trop abordé les détails, c'est donc un supplément.

Qu'est-ce que pybind11

Liaisons Python C ++ pouvant être utilisées avec C ++ 11 ou version ultérieure. Vous pouvez publier un module créé en C ++ vers python. Recommandé pour ceux qui souhaitent utiliser C ++ pour un traitement fastidieux et python pour divers essais. *** Il y a des limites à la façon dont vous pouvez utiliser Numpy, il y a donc certaines parties que vous devez écrire en C ++. Récemment, je n'ai écrit que le minimum que je dois faire moi-même en C ++, et le reste est du style en utilisant scipy, scikit-image, etc. Il existe des options telles que Cython, mais la source C ++ est toujours plus facile que de rechercher et de déboguer le code C généré automatiquement.

Il existe plusieurs liaisons pour Python et C ++, dont Boost.Python. Cela lui-même est utile en tant que fonction. J'ai déjà écrit sur Boost.Python. (Cependant, l'histoire de l'utilisation de Python à partir de C ++)

L'une des raisons pour lesquelles Python est souvent utilisé dans le domaine des calculs scientifiques et technologiques est l'existence de Numpy, mais il existe une bibliothèque qui utilise Boost.Python appelée Boost.Numpy, et si vous l'utilisez, Numpy sera une fonction C ++. C'est très pratique car vous pouvez facilement transmettre les données créées. Ceci est également écrit avant.

Cependant, Boost.Python est ennuyeux car il nécessite la construction d'une bibliothèque. Il peut être mal compris que Boost.Python peut être utilisé à la fois dans les séries Python2 et Python3. Cependant, pour l'utiliser dans la série Python2, vous devez construire 2 séries, et pour l'utiliser dans la série Python3, vous devez construire 3 séries. Vous devez également choisir une version de débogage, un lien statique ou un lien dynamique. Bien sûr, Boost.Numpy doit également être construit.

Pybind11 est une alternative à un Boost.Python aussi ennuyeux.

Différence avec Boost.Python

--Pour les compilateurs C ++ 11 ou version ultérieure

Il ne peut pas être utilisé avec des compilateurs qui ne prennent pas en charge C ++ 11. Jetons un tel compilateur. Boost.Python est gonflé car il fonctionne avec des compilateurs plus anciens, mais pybind 11 est petit car il ne cible que C ++ 11 et les versions ultérieures.

Boost.Python nécessitait une construction de bibliothèque et était fastidieux à installer, mais pybind11 est uniquement en-tête, il est donc prêt à être utilisé. Je pense que cet avantage à lui seul est une raison de passer à pybind11.

La migration depuis Boost.Python est relativement simple. Si vous pouvez utiliser C ++ 11, considérez-le maintenant.

Coopération avec Eigen et Numpy

La coopération avec la bibliothèque de matrices C ++ Eigen et la bibliothèque de tableaux Python Numpy a déjà été envisagée. Vous n'avez pas besoin d'installer Boost.Numpy séparément comme Boost.Python, et vous n'avez pas besoin de créer une bibliothèque.

Installation

Comme il s'agit d'un en-tête uniquement, il suffit de le cloner ou de le télécharger depuis github et de le mettre dans votre répertoire préféré. Vous pourrez peut-être l'installer avec le gestionnaire de packages du système d'exploitation, mais il semble être mis à jour fréquemment, donc je pense que vous devriez l'obtenir depuis github. J'ai constaté que la version installée par Package Manager était ancienne et qu'il n'y avait aucune fonction qui devrait être dans la dernière version.

Exemple simple

Utilisons la fonction d'addition créée en C ++ à partir de Python. Identique à celui de la documentation officielle.

Code source C ++

cppmod.cpp


#include<pybind11/pybind11.h>
  
int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(cppmod, m) {
    m.doc() = "pybind11 example plugin";
    m.def("add", &add, "A function which adds tow numbers");
}

Puisqu'il s'agit d'une bibliothèque partagée, il n'y a pas de fonction principale. Le nom spécifié par PYBIND11_PLUGIN est le nom du module. En d'autres termes, lors de l'utilisation de Python, dans cet exemple, il s'agit de import cppmod.

Le py :: module '' suivant est une description du module. Le nom et la soi-disant docstring. Ensuite, spécifiez la fonction à publier sur python. Le dernier return m.ptr () '' n'était pas nécessaire dans Boost.Python, mais il devrait être ajouté dans pybind11.

Pour référence, dans le cas de Boost.Python

BOOST_PYTHON_MODULE(cppmod) {
    Py_Initialize();
    py::def("add",add); 
}

Ce sera. C'est presque pareil.

compiler

Compilez en tant que bibliothèque partagée (DLL pour Windows, mais avec l'extension .pyd). ~~ Depuis que j'utilise SCons, le fichier de configuration ressemble à ceci: Veuillez régler en fonction de l'environnement. À propos, SCons est un outil de construction pour Python. On dit qu'un gros projet est lent, mais la compilation C ++ elle-même est lente, donc je l'utilise sans m'en soucier. .. ~~ J'ai décidé d'utiliser cmake sans aller à l'encontre de la tendance. Écrivez quelque chose comme ce qui suit dans CMakeLists.txt.

CMakeLists.txt


cmake_minimum_required(VERSION 3.0)
  
project(cppmod)
set(PYBIND11_CPP_STANDARD -std=c++14)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -O2")
add_subdirectory(pybind11)

pybind11_add_module(cppmod SHARED cppmod.cpp)  

La commande build ressemble à ceci.

$ mkdir build && cd build
$ cmake ..
$ make

Exécuter à partir de Python

Tout d'abord, placez la bibliothèque partagée compilée (par exemple cppmod.cpython-36m-x86_64-linux-gnu.so '') dans le répertoire où vous souhaitez exécuter Python.

Ensuite, démarrez Python et importez-le. Tout d'abord, émettons de l'aide. Ça devrait ressembler à ça:

input


>>> import cppmod
>>> help(cppmod)

output


Help on module cppmod:

NAME
    cppmod - pybind11 example plugin

FUNCTIONS
    add(...) method of builtins.PyCapsule instance
        add(int, int) -> int

        A function which adds two numbers

FILE
    /path/to/cppmod.so

Le module, la description de la fonction (docstring), l'argument de la fonction et le type de retour, etc. sont affichés.

Ensuite, utilisons la fonction add.

>>> cppmod.add(2,3)
5

J'ai pu appeler une fonction créée en C ++.

Coopération avec Numpy

Utilisez l'en-tête pybind11 / numpy.h. Une classe appelée py :: array_t peut recevoir des données de type ndarray et les transmettre à Python.

#include<pybind11/pybind11.h>
#include<pybind11/numpy.h>
#include<algorithm>
namespace py = pybind11;

auto npadd(py::array_t<double> arr, const double v) {
    const auto size = arr.size();
    py::array_t<double> ret(size);
    std::transform(
        arr.data(),arr.data()+size,
        ret.mutable_data(), [v](autoe){returne+v;});
    return ret;
}

PYBIND11_MODULE(cppmod, m) {
    m.doc() = "pybind11 example plugin";
    m.def("npadd", &npadd, "A function which adds scalar to ndarray");
}

Exemple d'utilisation

>>> import cppmod
>>> import numpy as np
>>> x = np.arange(10)
>>> cppmod.npadd(x, 3.)
array([  3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.])

C'est très facile.

Difficulté

J'ai de la documentation, mais il semble qu'il n'y ait pas encore de référence pour les fonctions individuelles. Ce n'est pas grave si vous regardez le code source, mais peut-être que seuls les gens C ++ Chotdekir n'ont aucun problème.

fin

pybind11 C'est pratique, alors utilisons-le.

Recommended Posts

Utilisation des fonctions C ++ de python avec pybind11
Envelopper C ++ avec Cython pour une utilisation à partir de Python
Appeler C depuis Python avec DragonFFI
Utiliser Python et MeCab avec Azure Functions
Passer la liste de Python vers C ++ par référence dans pybind11
Utilisez Thingsspeak de Python
[Python] Utiliser JSON avec Python
Utiliser fluentd de python
Utilisez MySQL depuis Python
Utiliser mecab avec Python 3
Utiliser DynamoDB avec Python
Utiliser python avec docker
Utiliser MySQL depuis Python
Utilisez mecab-ipadic-neologd de Python
Curry n'importe quelle fonction avec Python ...
Introduction aux fonctions Python
Utiliser l'API Trello avec python
Utiliser TUN / TAP avec Python
Essayez d'incorporer Python dans un programme C ++ avec pybind11
Étude de Python Hour3: Fonctions
Créer un environnement pour exécuter des fonctions C ++ à partir de Python avec Pybind11 (pour les utilisateurs de Windows et Visual Studio Code)
Utiliser l'API subsonique avec python3
Avec skype, notifiez avec skype de python!
Utilisez l'API e-Stat de Python
Appeler des fonctions du langage C depuis Python pour échanger des tableaux multidimensionnels
Incorporer un interpréteur Python dans une application C ++ avec pybind11 + cmake
Résoudre ABC163 A ~ C avec Python
Python: comment utiliser async avec
Utiliser la PNL Stanford Core à partir de Python
Utiliser la caméra Point Grey avec Python (PyCapture2)
Utilisez vl53l0x avec RaspberryPi (python)
Utilisation de Rstan de Python avec PypeR
Installez Python à partir des sources avec Ansible
Appeler popcount depuis Ruby / Python / C #
Utilisez NAIF SPICE TOOL KIT avec Python
Lire et utiliser des fichiers Python à partir de Python
Utiliser de force Google Translate à partir de python
Utiliser rospy avec virtualenv dans Python3
Libre de codage en dur des fonctions avec SymPy
Résoudre ABC168 A ~ C avec Python
Exécutez Aprili depuis Python sur Orange
Utilisez l'API kabu Station® de Python
10 fonctions du "langage avec batterie" python
Conseils pour appeler Python à partir de C
Exécuter du code Python à partir de l'interface graphique C #
Utiliser Python mis en pyenv avec NeoVim
Utilisez l'API Flickr de Python
Utiliser la synthèse vocale Windows 10 avec Python
Résolu AtCoder ABC 114 C-755 avec Python3
Résoudre ABC162 A ~ C avec Python
Exécutez des scripts Python de manière synchrone à partir de C #
Résoudre ABC167 A ~ C avec Python
Appelez python de nim avec Nimpy