Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Tout d'abord, CMake.

Aperçu

Je veux faire du code écrit en C ++ une bibliothèque qui puisse être appelée en Python. Cependant, il y avait un grand mur appelé Cython.

C'est le tutoriel "Cython" qui rend Python explosif: quand le code C ++ dépend de la bibliothèque. Ceci est une suite de la section de préparation.

Le code est répertorié dans "github here", veuillez donc y jeter un œil.

En tant que structure de dossier minimale, c'était comme ça.

Explication de la situation

(myenv) user@~/Documents/cython_practice[master]> tree .
.
├── README.md
├── cpp_library
│   ├── TestClass1.cpp
│   └── TestClass1.h
├── cython
│   ├── my_library.pxd
│   ├── my_library.pyx
│   ├── test_class1.pxd
│   └── test_class1.pyx
└── setup.py

De plus, à la fin de la dernière fois,

wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz &&\
tar xvf gmp-6.1.2.tar.xz &&\
cd gmp-6.1.2 &&\
./configure --prefix=/usr/local/gmp/6_1_2 &&\
make && make check && make install

J'ai installé la bibliothèque gmp```.

Que faire cette fois

Cette fois, d'abord

  1. Écrivez du code simple à l'aide de la bibliothèque gmp et assurez-vous qu'il peut être compilé avec des commandes.
  2. Comment les bibliothèques C ++ sont-elles installées et référencées en premier lieu?
  3. Comment la compilation des programmes dépendants est-elle effectuée à l'aide de CMake?
  4. Comment est-il écrit dans setup.py lorsqu'il est converti en cython?

J'expliquerai jusqu'à 3. Concernant 4, j'utiliserai en fait Cython pour compiler un programme C ++ avec des dépendances afin qu'il puisse être appelé depuis Python, ce que j'écrirai dans le prochain article.

Dépendances C ++

Comment les bibliothèques C ++ sont-elles installées et référencées en premier lieu?

gmpIl s'agit de la commande lorsque la bibliothèque est installée.

./configure --prefix=/usr/local/gmp/6_1_2



 C'est là que stocker le fichier objet créé lors de la compilation avec `` `make` '' plus tard, et le fichier d'en-tête qui est la source du projet au moment de` `make install`` `. Est la commande spécifiée.

 S'il n'est pas spécifié, le fichier objet est essentiellement stocké dans `` `` / usr / local / lib` `` `` et le fichier d'en-tête requis (essentiellement un fichier d'en-tête contenant tous les fichiers de programme requis pour la bibliothèque). ) Est stocké dans `` `` / usr / local / include` ``.

 Après cela, il est compilé par `` `make` '', et le fichier objet et le fichier d'en-tête compilé par` `make install '' 'sont stockés.

 Ici, assurez-vous que le fichier objet et le fichier d'en-tête de la bibliothèque gmp sont réellement stockés dans le dossier spécifié.

```bash
root@e96f489c2395:/# ls /usr/local/gmp/6_1_2/lib/
libgmp.a  libgmp.la  libgmp.so  libgmp.so.10  libgmp.so.10.3.2
root@e96f489c2395:/# ls /usr/local/gmp/6_1_2/include/
gmp.h

Certes, le fichier objet se trouve sous / usr / local / gmp / 6_1_2 / lib, Le fichier d'en-tête est stocké sous `` `` / usr / local / gmp / 6_1_2 / include.

cmake

Comment la compilation des programmes dépendants est-elle effectuée à l'aide de CMake?

Par conséquent, pour créer et compiler un programme qui les utilise, vous devez compiler en référence à eux. Tout d'abord, utilisez simplement g ++ pour écrire un programme simple et le compiler.

test.cpp


#include <iostream>
#include <gmp.h>

using namespace std;

void print_test(){
    mpz_t test;
    mpz_init(test);
    mpz_set_ui(test, 1);
    gmp_printf("print : %Zd \n", test);
}

int main(){
    print_test();
}


Vous n'avez pas besoin de connaître la bibliothèque gmp, mais comme gmp est une bibliothèque qui calcule de grands entiers, c'est un programme qui attribue simplement 1 à un objet appelé test et l'imprime.

Compilez explicitement la bibliothèque avec des options. Bien sûr, si vous essayez de compiler sans rien écrire sur la bibliothèque, vous obtiendrez une erreur de référence.

root@e96f489c2395:/from_local# g++ test.cpp
/tmp/ccZnVmvP.o: In function `main':
test.cpp:(.text+0x1f): undefined reference to `__gmpz_init'
test.cpp:(.text+0x30): undefined reference to `__gmpz_set_ui'
test.cpp:(.text+0x48): undefined reference to `__gmp_printf'
collect2: error: ld returned 1 exit status

Ce sera. C'est bien sûr parce que les bibliothèques dépendantes ne sont pas spécifiées, mais en le résolvant,

root@e96f489c2395:/from_local# g++ test.cpp -L/usr/local/gmp/6_1_2/lib -I/usr/local/gmp/6_1_2/include -lgmp
root@e96f489c2395:/from_local# ./a.out
print : 1 

Bien sûr, vous pouvez compiler comme ça. Dans ce cas, -Lspécifie le chemin vers la bibliothèque (fichier objet),-i```Est une option de compilation qui spécifie le chemin d'accès au fichier d'en-tête.

Cependant, lorsque vous avez plusieurs bibliothèques dépendantes, ou lorsque vous avez plusieurs programmes que vous écrivez, compiler avec `` g ++ '' comme celui-ci peut être assez ennuyeux. Par conséquent, préparez CMakeLists.txt et compilez-le facilement.

Pour ce faire, créez le suivant CMakelists.txt`

cmake . &&Il est préférable de compiler en utilisant make.



 Ici, au lieu de créer `` `` CMakelists.txt` '' comme suit et de compiler avec la commande `` `g ++` `` `et les options,` `` `cmake. && make``` Je vais essayer de compiler en l'utilisant.


#### **`CMakeLists.txt`**
```txt

cmake_minimum_required(VERSION 3.10)

project(TEST VERSION 1.1.0 LANGUAGES CXX)

# Executable will be in ../bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
set(CMAKE_CXX_FLAGS "-g -O0 -lgmp")


add_executable(test1 
    test.cpp
    )

target_sources(test1
    PRIVATE
)

target_include_directories(test1 PRIVATE /usr/local/gmp/6_1_2/include/)
target_link_libraries(test1 gmp /usr/local/gmp/6_1_2/lib)

root@e96f489c2395:/from_local# cmake .
-- Configuring done
WARNING: Target "test1" requests linking to directory "/usr/local/gmp/6_1_2/lib".  Targets may link only to libraries.  CMake is dropping the item.
-- Generating done
-- Build files have been written to: /from_local
root@e96f489c2395:/from_local# make 
[100%] Built target test1
root@e96f489c2395:/from_local# ./test1
print : 1 

Résumé

En tant que connaissances nécessaires lors de la conversion d'un programme C ++ en cython, ce qui suit a été effectué pour réaliser la cythonisation d'un programme qui a une dépendance du côté C ++.

Dans le prochain article --Je vais expliquer comment écrire setup.py en fonction des dépendances.

Cette fois par ici.

fin.

Recommended Posts

Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Tout d'abord, CMake.
Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Préparation
Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Écrivez setup.py.
Tutoriel "Cython" pour rendre Python explosif: Passez l'objet de classe C ++ à l'objet de classe côté Python. Partie 2
Tutoriel "Cython" qui rend Python explosif: Gérer le passage de fonctions côté C ++ par référence.
Tutoriel "Cython" pour rendre Python explosif: configuration de base
Tutoriel "Cython" pour rendre Python explosif: Comment analyser la classe Enum définie en code C ++ vers Enum en Python.
Premier python ② Essayez d'écrire du code tout en examinant les fonctionnalités de python
Comment utiliser la bibliothèque C en Python
Je suis tombé sur un code de caractère lors de la conversion de CSV en JSON avec Python
Je veux créer du code C ++ à partir de code Python!
Faire un point d'arrêt sur la couche c avec python
Construction facile de code C ++ avec CMake sur Docker
J'ai senti que j'avais porté le code Python en C ++ 98.
[Introduction à Python] Utilisation basique de la bibliothèque matplotlib
Version compatible GPU de l'application LibTorch (PyTorch C ++) sur Windows sans CMake (uniquement la première fois)
Facilitez la compréhension de l'affichage des exceptions du module Python
La première API à créer avec le framework Python Djnago REST
Paramètres pour entrer et déboguer le contenu de la bibliothèque avec VS Code
Transmettez les données OpenCV de la bibliothèque C ++ d'origine à Python
Grâce à l'installation du package pip qui dépend de opencv-python lors de la construction d'opencv à partir du code source
Lorsque vous souhaitez utiliser plusieurs versions de la même bibliothèque Python (environnement virtuel utilisant venv)
Envelopper (partie de) la bibliothèque AtCoder en Cython pour une utilisation en Python
Différences que les ingénieurs C # ont ressenties lors de l'apprentissage de Python pour la première fois
Mesurez la couverture de test du code python poussé sur GitHub.
[Introduction à Python] J'ai comparé les conventions de nommage de C # et Python.
[Python] Comment obtenir le premier et le dernier jour du mois
J'ai écrit le code pour écrire le code Brainf * ck en python
Comment mettre à jour la version Python de Cloud Shell dans GCP
Comment exécuter le code pratique du livre "Making Profitable AI with Python" sur Google Colaboratory
First Python 3 ~ Le début de la répétition ~
Remarque Python: lorsque vous souhaitez connaître les attributs d'un objet
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
Téléchargez collectivement les images collées dans le corps de la pull request sur Github
J'ai essayé de vérifier et d'analyser l'accélération de Python par Cython
De la construction de ré-environnement de Python au dessin graphique (sur le code Visual Studio)
Code Python pour déterminer les signaux mensuels pour les investissements de force relative
[Python3] Code qui peut être utilisé lorsque vous souhaitez modifier l'extension d'une image à la fois
Comment gérer "^ [[A ^ [[B ^ [[C ^ [[D"]] en appuyant sur la touche de direction lors de l'exécution de python sur mac