Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Écrivez setup.py.

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. 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!

Explication de la situation

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)

Cython pour le moment

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

Comment les bibliothèques dépendantes sont-elles écrites dans 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. ..

Résumé

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

Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Écrivez setup.py.
Tutoriel "Cython" qui rend Python explosif: lorsque le code C ++ dépend de la bibliothèque. Tout d'abord, CMake.
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: Gérer le passage de fonctions côté C ++ par référence.
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: configuration de base
Tutoriel "Cython" pour rendre Python explosif: Comment analyser la classe Enum définie en code C ++ vers Enum en Python.
Comment utiliser la bibliothèque C en Python
Je veux créer du code C ++ à partir de code Python!
Je suis tombé sur un code de caractère lors de la conversion de CSV en JSON avec Python
Faire un point d'arrêt sur la couche c avec python
J'ai senti que j'avais porté le code Python en C ++ 98.
Transmettez les données OpenCV de la bibliothèque C ++ d'origine à Python
Comment écrire du code pour accéder à python dashDB sur Bluemix ou local
J'ai écrit le code pour écrire le code Brainf * ck en python
Essayez d'écrire du code python pour générer du code go - Essayez de porter JSON-to-Go et ainsi de suite
Exécuter du code Python sur C ++ (en utilisant Boost.Python)
Comment gérer "^ [[A ^ [[B ^ [[C ^ [[D"]] en appuyant sur la touche de direction lors de l'exécution de python sur mac
python setup.py tester le code en utilisant le multiprocessus
Rendre la bibliothèque créée par Eigen of C ++ disponible à partir de Python avec Boost.Numpy.
Lorsque vous ne pouvez pas désinstaller la bibliothèque python. Impossible de désinstaller «hogehoge». Aucun fichier à désinstaller n'a été trouvé.
Remarque sur l'encodage lorsque LANG = C en Python
Conseils pour rédiger un aplatissement concis en python
Introduction à Python avec Atom (en route)
Pour écrire dans Error Repoting en Python sur GAE
Une histoire bloquée lors de la tentative de mise à niveau de la version Python avec GCE
Comment passer des arguments lors de l'appel d'un script python depuis Blender sur la ligne de commande