Tutoriel "Cython" pour rendre Python explosif: Comment analyser la classe Enum définie en code C ++ vers Enum en Python.

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.

Voici le cours Bridge from C ++ to Python "Cython": Comment passer un objet de classe C ++ à un objet de classe côté Python. La partie 2 est une continuation.

Comme toujours, je posterai le code sur github here alors jetez un œil! !!

Explication de la situation

Supposons que vous définissiez une classe Enum du côté C ++ et que vous l'ayez comme propriété de la classe. À ce stade, lorsque vous obtenez cette propriété à l'aide de getter, etc., la valeur de retour est bien sûr la classe Enum. Lors de la conversion en Cython, cette valeur de retour est une classe qui n'est pas définie du côté Python, il est donc nécessaire de l'analyser et de la renvoyer après l'avoir définie en Cython.

Tout d'abord, examinons rapidement comment écrire Enum en C ++ et Python.

Comment écrire la classe Enum en C ++.


enum class Color{
    RED = 0,
    GREEN = 1,
    BLUE = 2
};

Comment écrire la classe Enum en Python.


class Color(Enum):
    RED = 0
    GREEN = 1
    BLUE = 2

J'ai ajouté la classe Enum du côté C ++ comme ceci.

Ajoutez la propriété (groupe) de la classe Enum à TestClass1.h et TestClass1.cpp qui ont été écrites jusqu'à présent. Nous avons également ajouté des getters et des setters pour la propriété de groupe en conséquence.

cpp_library/TestClass1.h



enum class EnumForTestClass1{
    ZERO = 0,
    ONE = 1
};

class TestClass1{
    private:
        TestClass2 property_test_class2;
        EnumForTestClass1 group;

    public:
        //~ abrégé

        void set_group(EnumForTestClass1 group);
        EnumForTestClass1 get_group();

cpp_library/TestClass1.cpp



EnumForTestClass1 TestClass1::get_group(){
    return this->group;
}

void TestClass1::set_group(EnumForTestClass1 group){
    this->group = group;
}

Ce getter et ce setter sont convertis en cython, c'est-à-dire que la classe Enum du côté C ++ et la classe Enum du côté Python sont connectées.

Comment passer la classe Enum du côté C ++ à la classe Enum du côté Python.

Comme d'habitude

cytyon/test_class1.C en pxd++Définissez la classe Enum latérale. La méthode de définition est divisée en fonction du fichier ci-dessous.


 Après cela, ajoutez les définitions du getter et du setter créés.



#### **`cython/test_class1.pxd`**
```pxd


cdef extern from "../cpp_library/TestClass1.h":
        cdef cppclass EnumForTestClass1:
            EnumForTestClass1()

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef EnumForTestClass1 ZERO
        cdef EnumForTestClass1 ONE  

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        #~ abrégé
        void set_group(EnumForTestClass1 group)
        EnumForTestClass1 get_group();    

Ajoutez également la même description à cython / my_library.pxd```.

cython/my_library.pxd


cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef cppclass EnumForTestClass1:
            EnumForTestClass1()

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef EnumForTestClass1 ZERO
        cdef EnumForTestClass1 ONE   

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        #~ abrégé
        void set_group(EnumForTestClass1 group)
        EnumForTestClass1 get_group();   

Une fois cela fait, l'étape suivante consiste à écrire le contenu du getter et du setter dans cython / tests_class1.pyx```. Si vous écrivez d'abord le code, il ressemblera à ceci:

cython/tests_class1.pyx


cpdef enum Py_EnumForTestClass1:
    Py_ZERO = 0
    Py_ONE = 1


cdef class TestClass1Cython:
    cdef TestClass1* ptr


    def set_group(self, Py_EnumForTestClass1 group):
        return self.ptr.set_group(<EnumForTestClass1> group)

    def get_group(self):
        cdef:
            EnumForTestClass1* cpp_enum_for_test_class1 = new EnumForTestClass1()
        cpp_enum_for_test_class1[0] = <EnumForTestClass1>self.ptr.get_group()

        if(<int>cpp_enum_for_test_class1[0] == <int>Py_EnumForTestClass1.Py_ZERO):
            return Py_EnumForTestClass1.Py_ZERO
        elif(<int>cpp_enum_for_test_class1[0] == <int>Py_EnumForTestClass1.Py_ONE):
            return Py_EnumForTestClass1.Py_ONE

Tout d'abord, définissez la classe Enum qui peut être appelée depuis Python avec cpdef enum Py_EnumForTestClass1```.

Ensuite, en ce qui concerne le setter, Py_EnumForTestClass1``` est reçu du côté Python, et il est passé à la fonction côté C ++ en le castant vers le type côté C ++ avec .

De plus, bien qu'il soit un peu redondant en ce qui concerne le getter, ce qui a été passé en tant qu'objet Enum du côté C ++ dans <EnumForTestClass1> self.ptr.get_group () '' est converti avec <int> et la valeur de cet int. L'instruction if détermine lequel des Py_EnumForTestClass1` '' du côté Python est égal à, et l'objet `` Py_EnumForTestClass1 '' est renvoyé en conséquence.

Avec ce qui précède, il est possible d'analyser la classe Enum du côté Python vers la classe Enum du côté C ++ et la classe Enum du côté C ++ de la classe Enum du côté Python.

Enfin, comme toujours

python setup.py install


 Compilons et testons avec.


#### **`test.py`**
```py

import my_library as myl

if __name__ == "__main__":
    cl1 = myl.test()
    test1 = myl.Py_EnumForTestClass1.Py_ZERO
    cl1.set_group(test1)

    test2 = cl1.get_group()
    print(test2)

Par conséquent,

(myenv) root@e96f489c2395:/from_local/cython_practice# python test.py 
0

Il a été confirmé que la classe Enum pouvait être définie et accéder à la propriété C ++.

Résumé

Cette fois, j'ai expliqué comment passer la classe Enum déclarée en C ++ à la classe Enum du côté Python lors de la conversion d'une bibliothèque écrite en C ++ en Cython afin qu'elle puisse être utilisée depuis Python.

À présent, vous devriez pouvoir transmettre la plupart des objets personnalisés du côté C ++ au côté Python.

La prochaine fois, j'aimerais écrire sur la façon dont Cython gère les surcharges de fonctions, qui sont souvent écrites du côté C ++.

Cette fois-ci.

fin.

Recommended Posts

Tutoriel "Cython" pour rendre Python explosif: Comment analyser la classe Enum définie en code C ++ vers Enum en Python.
Comment transformer une chaîne en tableau ou un tableau en chaîne en Python
Tutoriel "Cython" pour rendre Python explosif: Passez un objet de classe C ++ à un objet de classe côté Python. Partie ①
Tutoriel "Cython" pour rendre Python explosif: Lorsqu'une fonction côté C ++ a une surcharge.
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: lorsque le code C ++ dépend de la bibliothèque. Préparation
[Python] Comment rendre une classe itérable
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: configuration de base
Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Tout d'abord, CMake.
Essayez de créer un module Python en langage C
Comment créer un package Python à l'aide de VS Code
Tutoriel "Cython" qui rend Python explosif: Gérer le passage de fonctions côté C ++ par référence.
Comment utiliser la méthode __call__ dans la classe Python
Comment créer un package Python (écrit pour un stagiaire)
Comment vérifier si une valeur existe dans un type d'énumération
Comment créer une instance d'une classe particulière à partir de dict en utilisant __new__ () en python
Comment envelopper C en Python
[Introduction à Python] Comment utiliser la classe en Python?
Comment obtenir stacktrace en python
Comment utiliser __slots__ dans la classe Python
Comment utiliser la bibliothèque C en Python
Comment effacer un taple dans une liste (Python)
Comment générer une séquence en Python et C ++
Comment incorporer des variables dans des chaînes python
Comment créer un fichier JSON en Python
Comment notifier les canaux Discord en Python
[Python] Comment dessiner un histogramme avec Matplotlib
Je veux créer du code C ++ à partir de code Python!
Comment apporter des modifications à l'interpréteur Python dans Pycharm
Vous pouvez le faire en 3 minutes! Comment créer un code QR (GIF) fonctionnel!
Comment utiliser le multitraitement python (suite 3) apply_async en classe avec Pool en tant que membre
Analyser une chaîne JSON écrite dans un fichier en Python
Comment convertir / restaurer une chaîne avec [] en python
Expliquez en détail comment créer un son avec python
[Python] Comment développer des variables dans une chaîne de caractères
Comment créer un outil CLI interactif avec Golang
Comment transformer un fichier .py en fichier .exe
Comment créer un téléchargeur d'image avec Bottle (Python)
Comment exécuter une commande à l'aide d'un sous-processus en Python
[Python] Comment appeler une fonction de c depuis python (édition ctypes)
J'ai essayé de créer un générateur qui génère une classe conteneur C # à partir de CSV avec Python
[Python] Comment créer une liste de chaînes de caractères caractère par caractère
[Python] Comment créer une matrice de contiguïté / liste de contiguïté [Théorie des graphes]
Comment découper un bloc de plusieurs tableaux à partir d'un multiple en Python
Comment convertir un tableau en dictionnaire avec Python [Application]
Une histoire sur la façon de spécifier un chemin relatif en python.
Comment importer des fichiers où vous le souhaitez en Python
[Python] Comment écrire une instruction if en une phrase.
Comment définir plusieurs variables dans une instruction Python for
J'ai essayé "Comment obtenir une méthode décorée en Python"
Comment développer dans un environnement virtuel Python [Memo]
Comment obtenir la dernière (dernière) valeur d'une liste en Python
Comment obtenir une liste d'exceptions intégrées pour python
J'ai fait un chronomètre en utilisant tkinter avec python
[Python] Comment générer une table pandas dans un fichier Excel
Je veux ajouter un joli complément à input () en python