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 12:32] – 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 22: | Line 21: | ||
| programme python | programme python | ||
| </ | </ | ||
| + | |||
| + | <WRAP center round download 60%> | ||
| + | Ensemble des sources {{ : | ||
| + | </ | ||
| ===== Code C++ ===== | ===== Code C++ ===== | ||
| + | L' | ||
| + | * appel de fonction (hors classe) | ||
| + | * construction d'un objet | ||
| + | * surcharge de constructeur | ||
| + | * accès d' | ||
| + | * invocation de méthode | ||
| + | |||
| + | L' | ||
| + | |||
| + | {{ : | ||
| <code c++> | <code c++> | ||
| # | # | ||
| 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 49: | Line 65: | ||
| </ | </ | ||
| + | Le programme proprement dit (les données initiales et le comportement) se trouve dans un fichier '' | ||
| + | |||
| + | {{ : | ||
| <code c++> | <code c++> | ||
| #include < | #include < | ||
| #include " | #include " | ||
| + | </ | ||
| + | La trace sera affichée au moment de l' | ||
| + | <code c++> | ||
| string | string | ||
| getMsg () { | getMsg () { | ||
| Line 59: | 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 70: | 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 84: | Line 109: | ||
| ===== 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 99: | 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 106: | Line 145: | ||
| ===== Passerelle ===== | ===== Passerelle ===== | ||
| + | La liaison ce fait grâce à la bibliothèque Boost avec un ensemble de déclarations. | ||
| + | |||
| + | {{ : | ||
| <code c++> | <code c++> | ||
| #include < | #include < | ||
| Line 112: | 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> | ||
| cmake_minimum_required (VERSION 3.5) | cmake_minimum_required (VERSION 3.5) | ||
| Line 143: | 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 159: | 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 170: | 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> | ||
| + | mkdir build/ | ||
| + | cd build/ | ||
| + | cmake .. | ||
| + | make -j $(nproc) | ||
| + | </ | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | L' | ||
| + | </ | ||
| + | Nous avons indiqué " | ||
| + | <code bash> | ||
| + | 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> | <code bash> | ||
| - | $ mkdir build/ | ||
| - | $ cd build/ | ||
| - | $ cmake .. | ||
| - | $ make -j $(nproc) | ||
| - | $ export PYTHONPATH=" | ||
| - | $ ../ | ||
| coucou | coucou | ||
| hello, world | hello, world | ||
python/wrapper.1656160357.txt.gz · Last modified: 2022/06/25 12:32 by francois