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 "Cython" tutorial to make Python explosive: when a function on the C ++ side has an overload. This is a continuation of.
The code is listed in "github here", so please take a look.
Last time, I explained Cythonization when a function on the C ++ side is overloaded (when the configuration has the same function name but different arguments).
This time, I would like to explain how to handle a function on the C ++ side on the Cython side when passing it by reference instead of passing it by value as an argument. It's not very new, but when you actually try to write Cython, you often get annoyed by errors, so be sure to check it out! !!
--Since the function on the C ++ side was overloaded, it was solved using a cast like previous article. --The arguments of the function implemented on the C ++ side include those passed by reference. --If the argument is a reference type, an error will occur.
I will actually try it.
cpp_library/TestClass1.h
class TestClass1{
private:
TestClass2 property_test_class2;
EnumForTestClass1 group;
public:
//~abridgement
static void print_vector(vector<int> &x);
static void print_vector(vector<double> &x);
The difference from the last time is that the argument `` `xof
print_vector``` is changed from ** by value to passed by reference **.
cpp_library/TestClass1.cpp
void TestClass1::print_vector(vector<int> &x){
for(int i=0; i<x.size(); i++){
cout << x[i] << " ";
}
cout << endl;
}
void TestClass1::print_vector(vector<double> &x){
for(int i=0; i<x.size(); i++){
cout << x[i] << " ";
}
cout << endl;
}
When I try to build this with python setup.py install
as usual, I get the following error:
./cython/my_library.cpp:2414:69: error: cannot bind non-const lvalue reference of type 'std::vector<int>&' to an rvalue of type 'std::vector<int>'
__pyx_t_1 = __Pyx_void_to_None(__pyx_v_testclass1.print_vector(((std::vector<int> )__pyx_t_4))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 53, __pyx_L1_error)
The cast should be neat, but I get angry when it comes to passing by reference.
So, as a solution
What does that mean?
cython/test_class1.pyx
@staticmethod
def print_vector(list x):
cdef:
TestClass1 testclass1
vector[int] vec_int
vector[double] vec_double
if isinstance(x[0], int):
vec_int.resize(len(x))
for i in range(len(x)):
vec_int[i] = <int>x[i]
return testclass1.print_vector(vec_int)
elif isinstance(x[0], float):
vec_double.resize(len(x))
for i in range(len(x)):
vec_double[i] = <double>x[i]
return testclass1.print_vector(vec_double)
else:
raise Exception('TypeError')
will do. Now, with `cdef```, create ``` vector [int]
and ``` vector [double] ``
on the fly and pass it to the function.
Maybe the error I just got is passed by reference, but I don't know if it really exists! Don't worry! !! !!
I interpret that it was an error.
Therefore, it is good to prepare the entity and reassure it.
Then, as usual, `python setup.py install`
will pass the build.
By doing this, by writing the test code as follows,
test.py
import my_library as myl
if __name__ == "__main__":
cl1 = myl.test()
x = [1,2,3]
y = [1.1, 2.2, 3.3]
cl1.print_vector(x)
cl1.print_vector(y)
I was able to call the function properly.
(myenv) root@e96f489c2395:/from_local/cython_practice# python test.py
1 2 3
1.1 2.2 3.3
This time, I explained how to handle the function on the C ++ side when passing by reference instead of passing by value as an argument on the Cython side.
This time around.
end.
Recommended Posts