Je veux faire du code écrit en ** c ++ ** dans une ** bibliothèque ** qui peut être appelée par ** python **. Cependant, il y avait un grand mur appelé ** cython **.
Dépendances de bibliothèques sombres, construction d'un environnement qui vous donne envie de devenir fou. Conversion de type que je ne sais pas quoi faire. Ce sentiment de désespoir qui me fait me demander si j'écris en python, en c ++ ou ce que je fais.
J'ai un peu plus de temps pour toucher cython, alors j'aimerais le résumer petit à petit. Je suis un niveau débutant pour python, c ++ et cython, donc si vous avez des erreurs, faites-le moi savoir.
Cette fois, je viserai à ** cythoniser et appeler ** à partir de python en tant que bibliothèque ** du code C ++ très simple.
La ** structure de dossier ** minimale est la suivante.
hoge@~/Documents/cython_test> tree .
.
├── cython
│ ├── library_cython.pyx
│ ├── test_library.pxd
│ └── test_library.pyx
├── my_library
│ ├── test.cpp
│ └── test.h
└── setup.py
2 directories, 6 files
setup.py Tout d'abord, setup.py était nécessaire pour créer la bibliothèque.
test_library``` est le nom de la bibliothèque à lire par python.
En d'autres termes, après la construction, appelez import test_library
.
setup.py
from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize
from Cython.Distutils import build_ext
from distutils import sysconfig
ext_modules = [
Extension(
"test_library", sources=[
"./cython/test_library.pyx",
"./my_library/test.cpp"
],
language="c++"
)
]
setup(
name = "test_library",
cmdclass = {"build_ext": build_ext},
ext_modules= cythonize(ext_modules)
)
En ce moment,
Extension(
"test_library", sources=[
"./cython/test_library.pyx",
setup(
name = "test_library",
Gardons les noms des trois `` test_library '' qui apparaissent dans. J'étais accro ici.
Créez une classe appelée TestClass '' du côté c ++. Appelez cela depuis python via cython. Pour plus de simplicité, TestClass n'a qu'un constructeur et une méthode appelée
test_function1 () ''.
À ce stade, attachons correctement l'espace de noms. Je ne sais pas pourquoi, mais c'est plus pratique lors de la conversion en cython. Ici, l'espace de noms est
my_library```.
test.h
namespace my_library
{
class TestClass{
public:
TestClass();
void test_function1();
};
} // namespace my_library
Écrivez le contenu de la fonction définie dans l'en-tête.
test_function1 () '' `` est juste une fonction à imprimer.
test.cpp
#include <iostream>
#include "test.h"
using namespace std;
namespace my_library{
TestClass::TestClass(){};
void TestClass::test_function1(){
cout << "printed from cpp function" << endl;
}
}
Comme vous pouvez le voir dans setup.py,
test_library.pyx est le fichier cython principal. Inclut `` `` library_cython.pyx
ci-dessous.
test_library.pyx
import cython
cimport cython
include "library_cython.pyx"
def test():
return TestClassCython()
Le fichier
pxd``` est comme un fichier de définition pour transmettre les informations nécessaires à test_library.pyx depuis C ++. Maintenant, nous avons vraiment besoin de réécrire ce qui a été défini dans l'en-tête c ++ sous la forme de cython.
test_library.pxd
cdef extern from "../my_library/test.h" namespace "my_library":
cdef cppclass TestClass:
TestClass()
void test_function1()
Dans cette `` bibliothèque_cython.pyx '', nous définirons la classe python (cython?) Qui est en fait appelée du côté python. Le premier casse-tête consiste à conserver le pointeur de la classe définie en c ++ comme variable membre de la classe. Le constructeur construit une classe côté c ++ et transmet son adresse à cette variable membre ptr. Le destructeur efface ce ptr avec del.
De plus, la méthode `test_function1_cython ()`
appelle en interne la méthode définie côté c ++ en la définissant sur
ptr.test_function1 ()
``.
library_cython.pyx
import cython
cimport cython
cdef class TestClassCython:
cdef TestClass* ptr
def __cinit__(self):
self.ptr = new TestClass()
def __deadaloc(self):
del self.ptr
def test_function1_cython(self):
self.ptr.test_function1()
Lorsque ce qui précède est prêt,
python setup.py install
ça ira. Si vous construisez avec succès, entrez l'interpréteur python et
Python 3.6.7 (default, Nov 16 2019, 21:57:19)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_library
>>> a = test_library.test()
>>> a.test_function1_cython()
printed from cpp function
>>>
Je serais heureux si je pouvais faire ça.
Donc, en utilisant cython, j'ai essayé d'appeler une classe écrite en c ++ à partir de python via une bibliothèque. Ce n'est que le début, et les dépendances peuvent être déroutantes, par exemple lors de l'utilisation d'une bibliothèque qui doit être compilée avec c ++, mais j'aimerais réécrire pour un cas légèrement plus sombre.
Si vous le trouvez utile, nous nous réjouissons de vos goûts et commentaires! !!
fin.
Recommended Posts