I want to make the code written in C ++ a library that can be called in Python. However, there was a big wall called Cython.
This is a "Cython" tutorial that makes Python explosive: Pass a C ++ class object to a class object on the Python side. It is a continuation of that ①.
The code is listed in "github here", so please take a look.
Last time, I explained that when a library written in C ++ is converted to Cython so that it can be used from Python, the type declared in C ++ is passed to the Python side.
It turned out that if you pass int or double itself, or vector that has them as elements, it will be converted to an appropriate type on the Python side.
This time, I will explain how to return an object of a class defined by yourself in C ++ code to the Python side.
I created a new TestClass2
like this for testing.
The configuration is such that TestClass1
has the object of
TestClass2 as a property. In order to receive the property, prepare a constructor that receives `` `getter
and setter
, TestClass2.
cpp_library/TestClass2.h
namespace my_library
{
class TestClass2{
private:
int property_int;
public:
TestClass2(){};
};
} // namespace my_library
cpp_library/TestClass2.cpp
cpp_library/TestClass1.h
#pragma once
#include <gmp.h>
#include <vector>
#include "TestClass2.h"
using namespace std;
namespace my_library
{
class TestClass1{
private:
TestClass2 property_test_class2;
public:
//abridgement
TestClass1(TestClass2 test_class2);
TestClass2 get_property_test_class2();
};
} // namespace my_library
cpp_library/TestClass1.cpp
//abridgement
TestClass1::TestClass1(){
this->property_test_class2 = TestClass2();
}
TestClass1::TestClass1(TestClass2 test_class2){
this->property_test_class2 = test_class2;
}
TestClass2 TestClass1::get_property_test_class2(){
return this->property_test_class2;
}
void TestClass1::set_property_test_class2(TestClass2 test_class2){
this->property_test_class2 = test_class2;
}
The implementation looks like this.
testclass2cython
Is
testclass2
It is a wrapper class for passing to python corresponding to.
cython/test_class2.pxd
cdef extern from "../cpp_library/TestClass2.h" namespace "my_library":
cdef cppclass TestClass2:
TestClass2()
cython/test_class2.pyx
cdef class TestClass2Cython:
cdef TestClass2* ptr
def __cinit__(self):
self.ptr = new TestClass2()
def __deadaloc(self):
del self.ptr
cython/test_class1.pxd
from libcpp.vector cimport vector
from libcpp.string cimport string
from test_class2 cimport *
cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
cdef cppclass TestClass1:
TestClass1()
TestClass1(TestClass2 test_class2)
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)
void set_property_test_class2(TestClass2 test_class2)
TestClass2 get_property_test_class2()
The important thing here is
--Declare the class object on the C ++ side as `cdef TestClass2 cpp_test_class2``` and --Declare the class object on the Python side as
test_class2 = TestClass2Cython ()
. --The return value from C ++ is first stored in the C ++ class object, and then the return value on the C ++ side is passed to the Python side with
`test_class2.ptr [0] = cpp_test_class2```.
Here, `test_class2.ptr``` is defined in test_class2.pyx as
cdef TestClass2 * ptr```, and ``
self.ptr [0] `` is a C ++ class object. Means the substance of. Since ``` get_property_test_class2 ()
`` on the C ++ side returned the substance of the class object of TestClass2, it was necessary to set it as
self.ptr [0]
.
cython/test_class2.pyx
def get_property_test_class2(self):
cdef:
TestClass2 cpp_test_class2
test_class2 = TestClass2Cython()
cpp_test_class2 = self.ptr.get_property_test_class2()
test_class2.ptr[0] = cpp_test_class2
return test_class2
As usual, after compiling with python setup.py install
(myenv) root@e96f489c2395:/from_local# 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
>>> test = my_library.test()
>>> test.get_property_test_class2()
<my_library.TestClass2Cython object at 0x7f776003d240>
And you can see that the `` `TestClass2from the C ++ side is passed to the
TestClass2Cython``` and can be recognized by the Python side.
For the object of the class defined on the C ++ side, it was found that it is necessary to define the receiving class on the Cython side and convert the return value of the function to that type and return it.
It's natural to say that, but it's surprisingly difficult, so I hope it helps.
Next, I would like to explain how to pass a class object on the Python side to C ++ via Cython, contrary to this time.
This time around here.
end.
Recommended Posts