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. Tout d'abord, CMake. Ce sera une continuation de.
Jusqu'à présent, nous avons vu comment compiler confortablement un programme C ++ qui dépend de la bibliothèque gmp en utilisant cmake. A partir de là, le sujet principal est enfin d'écrire le code pour cythoniser ce programme C ++ et de le compiler avec setup.py.
Le code utilisé ici peut être trouvé sur github here, donc si vous êtes intéressé, jetez un œil!
Dans l'article précédent, j'avais besoin de comprendre les dépendances de mon programme C ++ afin d'écrire setup.py en premier lieu.
--Dépendances faciles à déclencher lors de l'écriture de programmes C ++ --À propos de la compilation de C ++ à l'aide de CMake
J'ai expliqué. Cette fois, j'écrirai le code qui convertit réellement la fonction C ++ en Cython, j'écrirai setup.py en référence au fichier CMakeLists.txt précédent, et le compilerai afin qu'il puisse être appelé depuis Python.
Le code côté C ++ est également inclus en tant que révision.
cpp_library/TestClass1.h
#include <gmp.h>
namespace my_library
{
class TestClass1{
public:
TestClass1();
void test_function1();
static void gmp_print_test();
};
} // namespace my_library
cpp_library/TestClass1.cpp
#include <iostream>
#include "TestClass1.h"
using namespace std;
namespace my_library{
TestClass1::TestClass1(){};
void TestClass1::test_function1(){
cout << "printed from cpp function" << endl;
}
void TestClass1::gmp_print_test(){
mpz_t test;
mpz_init(test);
mpz_set_ui(test, 1);
gmp_printf("print : %Zd \n", test);
}
}
Si vous avez un tel test.cpp '', assurez-vous de pouvoir le compiler avec le
CMakeLists.txt '' suivant.
cpp_library/test.cpp
#include "TestClass1.h"
using namespace my_library;
int main(){
TestClass1::gmp_print_test();
}
cpp_library/CMakeLists.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
TestClass1.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)
Tout d'abord, écrivez le code cython comme suit pour encapsuler la fonction C ++. Comme je l'ai fait auparavant, le fichier pxd était le fichier d'en-tête cython et le fichier pyx était le fichier du corps du programme cython. Écrivez pour encapsuler C ++ comme suit.
cython/test_class1.pxd
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
cdef cppclass TestClass1:
TestClass1()
void test_function1()
void gmp_print_test()
cython/test_class1.pxd
import cython
cimport cython
cdef class TestClass1Cython:
cdef TestClass1* ptr
def __cinit__(self):
self.ptr = new TestClass1()
def __deadaloc(self):
del self.ptr
def test_function1_cython(self):
self.ptr.test_function1()
@staticmethod
def gmp_print_test():
cdef TestClass1 testclass1
testclass1.gmp_print_test()
cython/my_library.pxd
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
cdef cppclass TestClass1:
TestClass1()
void test_function1()
void gmp_print_test()
cython/my_library.pyx
import cython
cimport cython
include "test_class1.pyx"
def test():
return TestClass1Cython()
setup.py
À partir de là, écrivez clairement setup.py pour indiquer qu'il dépend de la bibliothèque gmp.
En fait, si vous savez déjà comment écrire `` CMakeLists.txt '', c'est une tâche facile. Comme vous pouvez le voir,
libraries=["gmp"],
library_dirs=["/usr/local/lib", "/usr/local/gmp/6_1_2/lib"],
include_dirs=["/usr/local/gmp/6_1_2/include"],
comme,
--Bibliothèques dépendantes
Tout comme lorsque vous avez écrit CMakeLists.txt.
En conséquence, j'ai créé le setup.py suivant.
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(
"my_library", sources=["./cython/my_library.pyx",
"./cpp_library/TestClass1.cpp"
],
libraries=["gmp"],
library_dirs=["/usr/local/lib", "/usr/local/gmp/6_1_2/lib"],
include_dirs=["/usr/local/gmp/6_1_2/include"],
language="c++",
extra_compile_args=['-std=c++1z',"-lgmp"]
),
]
setup(
name = 'my_library',
cmdclass = {'build_ext': build_ext},
ext_modules = cythonize(ext_modules)
)
Après avoir terminé ce qui précède, vous avez réussi à convertir le programme C ++ qui dépend de la bibliothèque gmp en cython.
python setup.Je l'ai essayé avec py install et il se compile. Je vais essayer de l'appeler correctement du côté python.
```bash
(myenv) root@e96f489c2395:/from_local/cython_practice# python
Python 3.6.3 (default, Jan 30 2020, 06:37:54)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import my_library
>>> my_library.TestClass1Cython.gmp_print_test()
print : 1
génial. ..
Cette fois, j'ai expliqué comment utiliser Cythonize lorsque le code côté C ++ dépend d'une bibliothèque (bibliothèque gmp dans l'exemple), et j'ai pu le compiler.
Ensuite, j'expliquerai comment passer un objet de classe côté C ++ à un objet de classe en Python. Personnellement, je pense que la plupart des choses peuvent être faites si vous savez comment le remettre, alors jetez un œil! !!
Si vous le trouvez utile, je serais ravi d'entendre LGTM, des commentaires et plus encore.
Cette fois par ici.
fin.
Recommended Posts