"Cython" Tutorial to Make Python Explosive: Basic Configuration

Overview

I want to make the code written in ** c ++ ** into a ** library ** that can be called by ** python **. However, there was a big wall called ** cython **.

Dependencies of deep dark libraries, building an environment that makes you want to go crazy. Type conversion that I don't know what to do. That feeling of despair that makes me wonder if I'm writing python, c ++, or what I'm doing.

I have a little more time to touch cython, so I would like to summarize it little by little. I'm a beginner level in python, c ++, and cython, so if you have any mistakes, please let me know.

Contents

This time, I will aim to ** cythonize a very simple c ++ code and call it from python as a library **.

The minimum ** folder structure ** is as follows.

hoge@~/Documents/cython_test> tree .
.
├── cython
│   ├── library_cython.pyx
│   ├── test_library.pxd
│   └── test_library.pyx
├── my_library
│   ├── test.cpp
│   └── test.h
└── setup.py

2 directories, 6 files

setup.py The first is setup.py, which is needed to build the library.

`` `test_library``` is the name of the library to be read by python.

In other words, after building, call import test_library.

setup.py


from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize
from Cython.Distutils import build_ext
from distutils import sysconfig

ext_modules = [
    Extension(
        "test_library", sources=[
            "./cython/test_library.pyx",
            "./my_library/test.cpp"
        ],
        language="c++"
    )
]

setup(
    name = "test_library",
    cmdclass = {"build_ext": build_ext},
    ext_modules= cythonize(ext_modules)
)

At this time,

    Extension(
        "test_library", sources=[
            "./cython/test_library.pyx",

setup(
    name = "test_library",

Let's keep the names of the three test_librarys that appear in. I was addicted to it here.

Code on the c ++ side

Create a class called TestClass on the c ++ side. Call this from python via cython. For simplicity, TestClass only has a constructor and a method called `test_function1 ()`. At this time, let's attach the namespace properly. I'm not sure why, but this is more convenient when converting to cython. Here, the namespace is my_library.

test.h


namespace my_library
{
class TestClass{
    public:
        TestClass();
        void test_function1();
};    
} // namespace my_library


Write the contents of the function defined in the header. `test_function1 ()` is just a function to print.

test.cpp


#include <iostream>
#include "test.h"
using namespace std;

namespace my_library{

TestClass::TestClass(){};
void TestClass::test_function1(){
    cout << "printed from cpp function" << endl;
}


}

Code on the cython side

As you can see in setup.py, `` `test_library.pyxis the main cython file. Includes library_cython.pyx``` below.

test_library.pyx


import cython
cimport cython

include "library_cython.pyx"

def test():
    return TestClassCython()

The `` `pxd``` file is like a definition file for passing the necessary information to test_library.pyx from c ++. Now we really need to write again in the form of cython what was defined in the c ++ header.

test_library.pxd


cdef extern from "../my_library/test.h" namespace "my_library":
    cdef cppclass TestClass:
        TestClass()
        void test_function1()

In this `` `library_cython.pyx```, we will define the python (cython?) Class that is actually called on the python side. The first confusing thing is to keep a pointer to a class defined in c ++ as a member variable of the class. In the constructor, construct the class on the c ++ side and pass its address to the ptr of this member variable. The destructor is erasing this ptr with del.

Also, the `test_function1_cython ()` method internally calls the method defined on the c ++ side by setting it to ptr.test_function1 ()` ``.

library_cython.pyx


import cython
cimport cython

cdef class TestClassCython:
    cdef TestClass* ptr

    def __cinit__(self):
        self.ptr = new TestClass()

    def __deadaloc(self):
        del self.ptr

    def test_function1_cython(self):
        self.ptr.test_function1()

If you can build it, praise yourself.

When the above is ready,


python setup.py install

will do. If you build successfully, enter the python interpreter and


Python 3.6.7 (default, Nov 16 2019, 21:57:19) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_library
>>> a = test_library.test()
>>> a.test_function1_cython()
printed from cpp function
>>> 

I would be happy if I could do that.

Summary

So, using cython, I tried to call a class written in c ++ from python via a library. This is just the beginning, and the dependencies can get confusing, for example when using a library that needs to be compiled in c ++, but I'd like to write again for a slightly darker case.

If you find it helpful, we welcome your likes and comments! !!

end.

Recommended Posts

"Cython" Tutorial to Make Python Explosive: Basic Configuration
"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
"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 C ++ code depends on the library. Write setup.py.
"Cython" tutorial to make Python explosive: When a function on the C ++ side has an overload.
"Cython" tutorial to make Python explosive: How to parse an Enum class defined in C ++ code into a Python Enum.
"Cython" tutorial to make Python explosive: When C ++ code depends on the library. First of all, CMake.
"Cython" tutorial to make Python explosive: Handling when a function on the C ++ side is passed by reference.
How to make a crawler --Basic
[Python Tutorial] An Easy Introduction to Python
Tips to make Python here-documents easier to read
[Python] How to make a class iterable
Fractal to make and play with Python
Python tutorial
I tried to touch Python (basic syntax)
I want to make a game with Python
Try to make a "cryptanalysis" cipher with Python
[Blender x Python] How to make an animation
Try to make a dihedral group with Python
How to make Substance Painter Python plugin (Introduction)
[Blender x Python] How to make vertex animation
I want to make C ++ code from Python code!
How to make Python faster for beginners [numpy]
How to make Python Interpreter changes in Pycharm
Lark Basics (Python, Lark to make a shell-like guy)
[Introduction to Python] Basic usage of lambda expressions
Updated to Python 2.7.9
RF Python Basic_01
Python Django Tutorial (5)
Python Django Tutorial (2)
Python tutorial summary
Basic Python writing
Python3 basic grammar
RF Python Basic_02
Python Django Tutorial (7)
Python Django Tutorial (1)
Python Django tutorial tutorial
Python Django Tutorial (3)
"Backport" to python 2
Python Django Tutorial (4)
Tool to make mask image for ETC in Python
Python beginners try adding basic auth to Django admin
Try to make a Python module in C language
Try to make a command standby tool with python
Explain in detail how to make sounds with python
Continuation ・ I tried to make Slackbot after studying Python3
Read the xml file by referring to the Python tutorial
How to make a Python package using VS Code
[Python] I want to make a nested list a tuple
[Introduction to Python] Basic usage of the library matplotlib