"Cython" tutorial to make Python explosive: How to parse an Enum class defined in C ++ code into a Python Enum.

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 Bridge from C ++ to Python "Cython" course: How to pass a C ++ class object to a class object on the Python side. Part 2 is a continuation.

As usual, I'll post the code on github here so please have a look! !!

Situation explanation

Suppose you define an Enum class on the C ++ side and have it as a property of the class. At this time, when you get this property using getter etc., the return value is of course the Enum class. When converting this to Cython, this return value is a class that is not defined on the Python side, so it is necessary to parse and return it after defining it in Cython.

First, let's take a quick look at how to write Enums in C ++ and Python.

How to write an Enum class in C ++.


enum class Color{
    RED = 0,
    GREEN = 1,
    BLUE = 2
};

How to write an Enum class in Python.


class Color(Enum):
    RED = 0
    GREEN = 1
    BLUE = 2

I added the Enum class from the C ++ side like this.

Add the property (group) of the Enum class to TestClass1.h and TestClass1.cpp that have been written so far. We also added getters and setters for the group property accordingly.

cpp_library/TestClass1.h



enum class EnumForTestClass1{
    ZERO = 0,
    ONE = 1
};

class TestClass1{
    private:
        TestClass2 property_test_class2;
        EnumForTestClass1 group;

    public:
        //~abridgement

        void set_group(EnumForTestClass1 group);
        EnumForTestClass1 get_group();

cpp_library/TestClass1.cpp



EnumForTestClass1 TestClass1::get_group(){
    return this->group;
}

void TestClass1::set_group(EnumForTestClass1 group){
    this->group = group;
}

This getter and setter are converted to cython, that is, the Enum class on the C ++ side and the Enum class on the Python side are connected.

How to pass the Enum class from the C ++ side to the Enum class on the Python side.

As usual

cytyon/test_class1.C to pxd++Define the side Enum class. The definition method is divided according to the file below.


 After that, add the definitions of the created getter and setter.



#### **`cython/test_class1.pxd`**
```pxd


cdef extern from "../cpp_library/TestClass1.h":
        cdef cppclass EnumForTestClass1:
            EnumForTestClass1()

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef EnumForTestClass1 ZERO
        cdef EnumForTestClass1 ONE  

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        #~abridgement
        void set_group(EnumForTestClass1 group)
        EnumForTestClass1 get_group();    

Also, add the same description to cython / my_library.pxd.

cython/my_library.pxd


cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef cppclass EnumForTestClass1:
            EnumForTestClass1()

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
        cdef EnumForTestClass1 ZERO
        cdef EnumForTestClass1 ONE   

cdef extern from "../cpp_library/TestClass1.h" namespace "my_library":
    cdef cppclass TestClass1:
        #~abridgement
        void set_group(EnumForTestClass1 group)
        EnumForTestClass1 get_group();   

Once this is done, the next step is to write the contents of the getter and setter in cython / tests_class1.pyx. If you write the code first, it will look like this:

cython/tests_class1.pyx


cpdef enum Py_EnumForTestClass1:
    Py_ZERO = 0
    Py_ONE = 1


cdef class TestClass1Cython:
    cdef TestClass1* ptr


    def set_group(self, Py_EnumForTestClass1 group):
        return self.ptr.set_group(<EnumForTestClass1> group)

    def get_group(self):
        cdef:
            EnumForTestClass1* cpp_enum_for_test_class1 = new EnumForTestClass1()
        cpp_enum_for_test_class1[0] = <EnumForTestClass1>self.ptr.get_group()

        if(<int>cpp_enum_for_test_class1[0] == <int>Py_EnumForTestClass1.Py_ZERO):
            return Py_EnumForTestClass1.Py_ZERO
        elif(<int>cpp_enum_for_test_class1[0] == <int>Py_EnumForTestClass1.Py_ONE):
            return Py_EnumForTestClass1.Py_ONE

First, define the Enum class that can be called from Python with `` `cpdef enum Py_EnumForTestClass1```.

Next, regarding the setter, `Py_EnumForTestClass1``` is received from the Python side, and it is passed to the C ++ side function by casting it to the C ++ side type with <EnumForTestClass1> ``.

Also, although the getter is a little redundant, what was passed as an Enum object on the C ++ side in `<EnumForTestClass1> self.ptr.get_group ()` is cast with and the value of that int. The if statement determines which of the Py_EnumForTestClass1` `` on the Python side is equal to, and returns the `` `Py_EnumForTestClass1 object accordingly.

With the above, it is possible to parse the Enum class on the Python side to the Enum class on the C ++ side, and the Enum class on the C ++ side to the Enum class on the Python side.

Finally, as always

python setup.py install


 Compile with and test it.


#### **`test.py`**
```py

import my_library as myl

if __name__ == "__main__":
    cl1 = myl.test()
    test1 = myl.Py_EnumForTestClass1.Py_ZERO
    cl1.set_group(test1)

    test2 = cl1.get_group()
    print(test2)

as a result,

(myenv) root@e96f489c2395:/from_local/cython_practice# python test.py 
0

It was confirmed that the Enum class could be set and get to the C ++ property.

Summary

This time, I explained how to pass the Enum class declared in C ++ to the Enum class on the Python side when converting a library written in C ++ to Cython so that it can be used from Python.

By now, I think most C ++ custom objects can be passed to Python.

Next time, I would like to write about how Cython handles function overloads, which are often written on the C ++ side.

This time around.

end.

Recommended Posts

"Cython" tutorial to make Python explosive: How to parse an Enum class defined in C ++ code into a Python Enum.
How to make a string into an array or an array into a string in Python
"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: Pass the C ++ class object to the class object on the Python side. Part 2
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. Preparation
[Python] How to make a class iterable
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. Write setup.py.
"Cython" Tutorial to Make Python Explosive: Basic Configuration
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. First of all, CMake.
Try to make a Python module in C language
How to make a Python package using VS Code
"Cython" tutorial to make Python explosive: Handling when a function on the C ++ side is passed by reference.
How to use the __call__ method in a Python class
How to make a Python package (written for an intern)
How to check if a value exists in an enum
How to create an instance of a particular class from dict using __new__ () in python
How to write a Python class
How to wrap C in Python
How to create a heatmap with an arbitrary domain in Python
[Introduction to Python] How to use class in Python?
How to get a stacktrace in python
How to use __slots__ in Python class
How to use the C library in Python
How to clear tuples in a list (Python)
How to generate permutations in Python and C ++
How to embed a variable in a python string
How to create a JSON file in Python
How to notify a Discord channel in Python
[Blender x Python] How to make an animation
[Python] How to draw a histogram in Matplotlib
I want to make C ++ code from Python code!
How to make Python Interpreter changes in Pycharm
You can do it in 3 minutes! How to make a moving QR code (GIF)!
How to use python multiprocessing (continued 3) apply_async in class with Pool as a member
Parse a JSON string written to a file in Python
How to convert / restore a string with [] in python
Explain in detail how to make sounds with python
[Python] How to expand variables in a character string
How to make an interactive CLI tool in Golang
How to turn a .py file into an .exe file
How to create an image uploader in Bottle (Python)
How to execute a command using subprocess in Python
[Python] How to call a c function from python (ctypes)
How to create a kubernetes pod from python code
I tried to make a generator that generates a C # container class from CSV with Python
[Python] How to make a list of character strings character by character
[Python] How to make an adjacency matrix / adjacency list [Graph theory]
How to slice a block multiple array from a multiple array in Python
How to convert an array to a dictionary with Python [Application]
A story about how to specify a relative path in python.
How to import a file anywhere you like in Python
[Python] How to write an if statement in one sentence.
How to define multiple variables in a python for statement
I tried "How to get a method decorated in Python"
How to develop in a virtual environment of Python [Memo]
How to get the last (last) value in a list in Python
How to get a list of built-in exceptions in python
I tried to make a stopwatch using tkinter in python
[Python] How to output a pandas table to an excel file
I want to make input () a nice complement in python