Ich möchte in C ++ geschriebenen Code zu einer Bibliothek machen, die in Python aufgerufen werden kann. Es gab jedoch eine große Mauer namens Cython.
Dies ist ein "Cython" -Tutorial, das Python explosiv macht: Wie man setup.py schreibt, wenn C ++ - Code von der Bibliothek abhängt. Es wird eine Fortsetzung von sein.
Der Code ist unter "github hier" aufgeführt. Schauen Sie also bitte vorbei.
Bis zum letzten Mal habe ich erklärt, wie setup.py geschrieben wird, um C ++ - Code Cython zu erstellen, wenn dies von der Bibliothek abhängt. Die einzige Funktion auf der C ++ - Seite, die zu diesem Zeitpunkt verwendet wurde, war der void-Typ. Ich denke jedoch natürlich, dass Funktionen häufig Funktionen schreiben, die Werte eines bestimmten Typs zurückgeben, anstatt void zu verwenden. Dieses Mal werde ich erklären, wie eine Funktion, die einen Typ auf der C ++ - Seite anstelle eines ungültigen Typs zurückgibt, in Cython erstellt und an die Python-Seite übergeben wird. Wenn Sie dies verstehen, können Sie noch viel mehr tun. Schauen Sie also bitte vorbei.
Wenn Sie Cython zum Umschließen einer C ++ - Bibliothek zur Verwendung in Python verwenden, analysiert die Python-Seite die C ++ - Klassendefinition nicht automatisch. Daher müssen Sie die Klasse für Python auf der Cython-Seite richtig definieren und mit der C ++ - Seite verbinden.
Es ist einfach zu schreiben, wenn man sich erst einmal daran gewöhnt hat, aber zuerst ist es schwer zu wissen, was zu tun ist, also werde ich das erklären.
Schreiben Sie als Beispiel `test_sum```, das int zurückgibt, und`
test_sum_double```, das auf der C ++ - Seite double zurückgibt.
cpp_library/TestClass1.h
#include <gmp.h>
namespace my_library
{
class TestClass1{
public:
TestClass1();
void test_function1();
static void gmp_print_test();
static int test_sum(int x, int y);
static double test_sum_double(double x, double y);
};
} // 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);
}
int TestClass1::test_sum(int x, int y){
return x+y;
}
double TestClass1::test_sum_double(double x, double y){
return x+y;
}
}
Zu diesem Zeitpunkt sieht der Cython-Code folgendermaßen aus:
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()
int test_sum(int x, int y)
double test_sum_double(double x, double y)
cython/test_class1.pyx
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()
@staticmethod
def test_sum(int x, int y):
cdef TestClass1 testclass1
return testclass1.test_sum(x, y)
@staticmethod
def test_sum_double(float x, float y):
cdef TestClass1 testclass1
return testclass1.test_sum_double(x, y)
Angenommen, Sie haben eine C ++ - Implementierung, die den Vektor
cpp_library/TestClass1.h
static vector<int> test_vector_int(vector<int> x, int y);
cpp_library/TestClass.cpp
vector<int> TestClass1::test_vector_int(vector<int> x, int y){
vector<int> result;
result.resize(x.size());
for(int i=0; i<x.size(); i++){
result[i] = x[i]*y;
}
return result;
}
cython/test_class1.pxd
from libcpp.vector cimport vector
from libcpp.string cimport string
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
cdef cppclass TestClass1:
TestClass1()
void test_function1()
void gmp_print_test()
int test_sum(int x, int y)
double test_sum_double(double x, double y)
vector[int] test_vector_int(vector[int] x, int y)
Das obige `von libcpp.vector cimport vector
erkennt den
vector
`auf der C ++ - Seite, so dass auf der Cython-Seite nicht viel zu tun ist. Es kann auf die gleiche Weise implementiert werden wie eine Funktion, die int oder double früher zurückgibt.
cython/test_class1.pyx
@staticmethod
def test_vector_int(list x, int y):
cdef TestClass1 testclass1
return testclass1.test_vector_int(x,y)
Wenn Sie tatsächlich `` `python setup.py install``` ausführen, können Sie bestätigen, dass die Kompilierung erfolgreich ist und diese Funktionen von der Python-Seite aufgerufen werden können.
(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.test_vector_int([1,2,3], 3)
[3, 6, 9]
Als nächstes werde ich es in einem Artikel schreiben.
Dieses Mal erklärte ich, dass beim Konvertieren einer in C ++ geschriebenen Bibliothek nach Cython, damit sie von Python aus verwendet werden kann, der in C ++ deklarierte Typ an die Python-Seite übergeben wird.
Es stellte sich heraus, dass wenn Sie int oder double selbst oder einen Vektor übergeben, der sie als Elemente enthält, dieser auf der Python-Seite in einen geeigneten Typ konvertiert wird. Es kann überraschend einfach implementiert werden.
Das nächste Mal werde ich erklären, wie ein Objekt einer von Ihnen in C ++ - Code definierten Klasse an die Python-Seite zurückgegeben wird. Es ist etwas komplizierter als int, double und vector mit ihnen als Elementen, aber es gibt viele Situationen wie diese in tatsächlichen Programmen, also schauen Sie bitte.
Diesmal hier.
Ende.
Recommended Posts