python:wrapper
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
python:wrapper [2022/06/25 14:27] – francois | python:wrapper [2022/06/28 08:38] (current) – luke | ||
---|---|---|---|
Line 4: | Line 4: | ||
L' | L' | ||
- | |||
|< | |< | ||
drwxr-xr-x 3 4096 build | drwxr-xr-x 3 4096 build | ||
Line 13: | Line 12: | ||
-rw-r--r-- 1 228 test.hpp | -rw-r--r-- 1 228 test.hpp | ||
-rwxr-xr-x 1 336 test.py | -rwxr-xr-x 1 336 test.py | ||
- | </ | + | </ |
répertoire pour créer les exécutables | répertoire pour créer les exécutables | ||
Règles de fabrication des binaires | Règles de fabrication des binaires | ||
Line 22: | Line 21: | ||
programme python | programme python | ||
</ | </ | ||
+ | |||
+ | <WRAP center round download 60%> | ||
+ | Ensemble des sources {{ : | ||
+ | </ | ||
===== Code C++ ===== | ===== Code C++ ===== | ||
Line 29: | Line 32: | ||
* construction d'un objet | * construction d'un objet | ||
* surcharge de constructeur | * surcharge de constructeur | ||
- | * accès | + | * accès |
* invocation de méthode | * invocation de méthode | ||
+ | |||
+ | L' | ||
{{ : | {{ : | ||
Line 37: | Line 42: | ||
using namespace std; | using namespace std; | ||
+ | </ | ||
+ | Déclaration d'une fonction | ||
+ | <code c++> | ||
string getMsg (); | string getMsg (); | ||
- | + | </ | |
+ | Déclaration d'une classe | ||
+ | <code c++> | ||
class Mem { | class Mem { | ||
private: | private: | ||
Line 56: | Line 64: | ||
}; | }; | ||
</ | </ | ||
+ | |||
+ | Le programme proprement dit (les données initiales et le comportement) se trouve dans un fichier '' | ||
{{ : | {{ : | ||
Line 62: | Line 72: | ||
#include " | #include " | ||
+ | </ | ||
+ | La trace sera affichée au moment de l' | ||
+ | <code c++> | ||
string | string | ||
getMsg () { | getMsg () { | ||
Line 68: | Line 80: | ||
return " | return " | ||
} | } | ||
+ | </ | ||
+ | Exemple de constructeurs surchargés. | ||
+ | <code c++> | ||
Mem::Mem (string msg) | Mem::Mem (string msg) | ||
: Mem (msg, 0) { | : Mem (msg, 0) { | ||
Line 79: | Line 93: | ||
Mem::~Mem () { | Mem::~Mem () { | ||
} | } | ||
+ | </ | ||
+ | Les accesseurs pour être utilisés pour simuler l' | ||
+ | <code c++> | ||
void | void | ||
Mem::set (string msg) { | Mem::set (string msg) { | ||
Line 92: | Line 108: | ||
===== Code Python ===== | ===== Code Python ===== | ||
+ | |||
+ | La première ligne permet de sélectionner le bon interpréteur. | ||
{{ : | {{ : | ||
<code python> | <code python> | ||
#! / | #! / | ||
+ | </ | ||
+ | Le nom du module correspond au nom de fichier suivi de l' | ||
+ | <code python> | ||
from libtest import getMsgPy, MemPy | from libtest import getMsgPy, MemPy | ||
+ | </ | ||
+ | Appel d'une fonction | ||
+ | <code python> | ||
print (getMsgPy ()) | print (getMsgPy ()) | ||
+ | </ | ||
+ | Création d'un objet C++ avec appel de constructeur. | ||
+ | <code python> | ||
word = MemPy (' | word = MemPy (' | ||
+ | </ | ||
+ | Liaison lecture/ | ||
+ | <code python> | ||
word.id = 1; | word.id = 1; | ||
print (f" | print (f" | ||
Line 109: | Line 136: | ||
word2 = MemPy (' | word2 = MemPy (' | ||
print (f" | print (f" | ||
+ | </ | ||
+ | Utilisation des accesseurs. | ||
+ | <code python> | ||
word2.msgPy = word.msgPy+" | word2.msgPy = word.msgPy+" | ||
print (word2.msgPy) | print (word2.msgPy) | ||
Line 115: | Line 144: | ||
===== Passerelle ===== | ===== Passerelle ===== | ||
+ | |||
+ | La liaison ce fait grâce à la bibliothèque Boost avec un ensemble de déclarations. | ||
{{ : | {{ : | ||
Line 123: | Line 154: | ||
using namespace boost:: | using namespace boost:: | ||
+ | </ | ||
+ | '' | ||
+ | <code c++> | ||
BOOST_PYTHON_MODULE (libtest) { | BOOST_PYTHON_MODULE (libtest) { | ||
- | | + | </code> |
+ | Le nom entre guillemets est l' | ||
+ | L' | ||
+ | <code c++> | ||
def (" | def (" | ||
+ | </ | ||
+ | La déclaration d'un constructeur est optionnelle. | ||
+ | <code c++> | ||
class_< | class_< | ||
+ | </ | ||
+ | On peut même ajouter la déclaration d' | ||
+ | <code c++> | ||
.def (init< | .def (init< | ||
+ | </ | ||
+ | Comme l' | ||
+ | Un pointeur sur un membre (ici une méthode) de la classe '' | ||
+ | <code c++> | ||
.def (" | .def (" | ||
.def (" | .def (" | ||
+ | </ | ||
+ | La liaison entre l' | ||
+ | <code c++> | ||
.def_readwrite (" | .def_readwrite (" | ||
+ | </ | ||
+ | Ici on a recours à des accesseurs. | ||
+ | Il faudra ne pas oublier le ";" | ||
+ | <code c++> | ||
.add_property (" | .add_property (" | ||
; | ; | ||
} | } | ||
- | |||
- | static bool initWrapper () { | ||
- | // | ||
- | // boost:: | ||
- | return true; | ||
- | } | ||
- | static bool isWrapperInit (initWrapper ()); | ||
</ | </ | ||
===== Compilation ===== | ===== Compilation ===== | ||
+ | |||
+ | Pour simplifier la création de la librairie C++ qui sera vu comme un module Python, nous avons utilisé '' | ||
+ | |||
{{ : | {{ : | ||
<code cmake> | <code cmake> | ||
Line 154: | Line 201: | ||
set (CMAKE_CXX_STANDARD 11) | set (CMAKE_CXX_STANDARD 11) | ||
set (CXX_STANDARD_REQUIRED ON) | set (CXX_STANDARD_REQUIRED ON) | ||
- | set (BUILD_SHARED_LIBS ON) | + | </ |
+ | <WRAP center round important 60%> | ||
+ | Il est important de produire une bibliothèque dynamique ('' | ||
+ | </ | ||
+ | <code cmake> | ||
+ | set (BUILD_SHARED_LIBS ON) | ||
+ | </ | ||
+ | Nous allons dépendre d' | ||
+ | <code cmake> | ||
find_package (PythonLibs 3 REQUIRED) | find_package (PythonLibs 3 REQUIRED) | ||
find_package (Boost REQUIRED python3 system chrono) | find_package (Boost REQUIRED python3 system chrono) | ||
+ | </ | ||
+ | Nous créons une liste de sources pour constituer notre bibliothèque. | ||
+ | <code cmake> | ||
list (APPEND libTestSrc | list (APPEND libTestSrc | ||
" | " | ||
" | " | ||
) | ) | ||
+ | </ | ||
+ | Répertoire où l'on trouve les entêtes nécessaires à la compilation. | ||
+ | <code cmake> | ||
include_directories ( | include_directories ( | ||
PUBLIC | PUBLIC | ||
Line 170: | Line 229: | ||
${PYTHON_INCLUDE_DIRS} | ${PYTHON_INCLUDE_DIRS} | ||
) | ) | ||
+ | </ | ||
+ | Compilation de tous les modules C++ et préparation de l' | ||
+ | <code cmake> | ||
add_library (test SHARED | add_library (test SHARED | ||
${libTestSrc} | ${libTestSrc} | ||
) | ) | ||
+ | </ | ||
+ | <WRAP center round important 60%> | ||
+ | Cette directive est indispensable. Sans quoi, on aura l' | ||
+ | </ | ||
+ | <code cmake> | ||
target_link_libraries (test | target_link_libraries (test | ||
${PYTHON_LIBRARIES} | ${PYTHON_LIBRARIES} | ||
Line 181: | Line 246: | ||
</ | </ | ||
+ | Installation du package '' | ||
+ | <code bash> | ||
+ | sudo apt-get install -y libboost-python-dev | ||
+ | </ | ||
+ | |||
+ | Nous allons créer les binaires dans un sous-répertoire '' | ||
<code bash> | <code bash> | ||
mkdir build/ | mkdir build/ | ||
Line 186: | Line 257: | ||
cmake .. | cmake .. | ||
make -j $(nproc) | make -j $(nproc) | ||
+ | </ | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | L' | ||
+ | </ | ||
+ | Nous avons indiqué " | ||
+ | <code bash> | ||
export PYTHONPATH=" | export PYTHONPATH=" | ||
+ | </ | ||
+ | |||
+ | Nous pouvons explicitement rendre le programme python exécutable et l' | ||
+ | <code bash> | ||
+ | chmod a+x ../test.py | ||
../ | ../ | ||
+ | </ | ||
+ | Voici le résultat en commençant par la trace réalisée dans l' | ||
+ | <code bash> | ||
coucou | coucou | ||
hello, world | hello, world |
python/wrapper.1656167227.txt.gz · Last modified: 2022/06/25 14:27 by francois