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.
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.
--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.
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.
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.
Utilisons la fonction d'addition créée en C ++ à partir de Python. Identique à celui de la documentation officielle.
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.
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
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 ++.
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.
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.
pybind11 C'est pratique, alors utilisons-le.
Recommended Posts