"Cython" tutorial to make Python explosive: Pass the C ++ class object to the class object on the Python side. Part 2

Overview

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.

Situation explanation

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;
}

How to receive TestClass2 in Python?

Define a wrapper class for Pyhton on Cython side and pass it to it.

The implementation looks like this.

testclass2cython Is testclass2It 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.

Summary

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

"Cython" tutorial to make Python explosive: Pass the C ++ class object to the class object on the Python side. Part 2
"Cython" tutorial to make Python explosive: Pass a C ++ class object to a class object on the Python side. Part ①
"Cython" tutorial to make Python explosive: When a function on the C ++ side has an overload.
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. Preparation
"Cython" tutorial to make Python explosive: Handling when a function on the C ++ side is passed by reference.
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. Write setup.py.
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. First of all, CMake.
"Cython" Tutorial to Make Python Explosive: Basic Configuration
"Cython" tutorial to make Python explosive: How to parse an Enum class defined in C ++ code into a Python Enum.
Make a breakpoint on the c layer with python
Pass OpenCV data from the original C ++ library to Python
Introduction to Python Hands On Part 1
[Python + heroku] From the state without Python to displaying something on heroku (Part 1)
[Python + heroku] From the state without Python to displaying something on heroku (Part 2)
[Python] How to make a class iterable
Try porting the "FORTRAN77 Numerical Computing Programming" program to C and Python (Part 1)
Try porting the "FORTRAN77 Numerical Computing Programming" program to C and Python (Part 3)
Try porting the "FORTRAN77 Numerical Computing Programming" program to C and Python (Part 2)
Python C / C ++ Extensions: Pass some of the data as np.array to Python (set stride)
How to use the C library in Python
Try to solve the Python class inheritance problem
Introduction to Python with Atom (on the way)
I want to make C ++ code from Python code!
Make it easy to install the ROS2 development environment with pip install on Python venv
How to pass arguments when invoking python script from blender on the command line
Think about how to program Python on the iPad
Try to make a Python module in C language
Steps to install the latest Python on your Mac
How to make unit tests Part.2 Class design for tests
Read the xml file by referring to the Python tutorial
Convert / return class object to JSON format in Python
I felt that I ported the Python code to C ++ 98.
How to enjoy Python on Android !! Programming on the go !!
Do not pass self to ProcessPoolExecutor in the class
[C / C ++] Pass the value calculated in C / C ++ to a python function to execute the process, and use that value in C / C ++.
I tried to make a generator that generates a C # container class from CSV with Python