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! !!
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.
enum class Color{
RED = 0,
GREEN = 1,
BLUE = 2
};
class Color(Enum):
RED = 0
GREEN = 1
BLUE = 2
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.
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 ++.
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