python:wrapper
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
python:wrapper [2022/06/25 12:31] – créée 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. |
+ | |||
+ | {{ : | ||
+ | < | ||
#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.1656160283.txt.gz · Last modified: 2022/06/25 12:31 by francois