# [Development] Cython with Python hello world
###### tags: `Python` , `Cython`, `extension module`
[toc]
## Goal
My intension here is just keeping pure python code secret and nothing to do with performance issue.
To show how to create an extension module and build it as a dynamic module *.so on Linux system. And import it and call the function in a pure python main program.
## Introduction

### Python vs Cython vs Jython
| Dimensions | Python | Cython | Jython |
|-|-|-|-|
| Introduction | Python is the traditional implementation of programming language, the one we probably use daily. | Cython is a superset of the Python programming language which additionally supports calling C/C++ functions. | Jython is mainly for integrating with the Java language. |
| Relation with Python Programming | Default Implementation | Alternative Implementation | Alternative Implementation |
| Compilation Process | compiles to .pyc | .pyx compiles to .c | compiles to .class |
| Extension | Extend with C | Extend with C | Extend with Java |
| Platform Dependency | Multi-platform | Multi-platform | 100% Java |
| Garbage Collector | [Python Garbage Collection](https://prepinsta.com/python/garbage-collection-in-python-programming-language/) | C Garbage Collection | Java Garbage Collection |
>**Cython** is a programming language that aims to be a superset of the Python programming language, designed to give C-like performance with code that is written mostly in Python with optional additional C-inspired syntax.
In general, we can use cython to convert the pure python code into compiled extension modules. This is a simple way to compile python modules to .so libraries, with a clear interface and which can be used by other python modules. It would be similar as building C and C++ extensions with distutils, except that the source code is python itself rather than C/C++. The idea is to organize all "secret code" into modules, compile them, and then import them in the rest of the python code which is not considered secret.
### Application of Cython
> Python programming will explicitly render calls to module C. Such C modules may be either generic C libraries or libraries specially designed for Python function. Cython produces the second form of the module: C libraries that refer to the internals of Python, and which can be combined with existing Python code. By default, Cython code looks very much like Python code. If you are feeding a Python program into the Cython compiler(Supporting both Python 2.x and Python 3.x), Cython must support it as-is, but neither of Cython ‘s native accelerations can come into effect. Yet if you decorate the Python code with the unique Cython syntax with form annotations, Cython would be able to substitute sluggish Python artifacts with fast C equivalents.
### Uses of Cython
>- Scientific and Numeric computations.
>- High Traffic Websites.
>- Designing Python Modules.
## Environment
```
Tomas# uname -a
Linux dfea0c2d8203 5.4.0-91-generic #102~18.04.1-Ubuntu SMP Thu Nov 11 14:46:36 UTC 2021 x86_64 Linux
Tomas# python3 --version
Python 3.8.10
```
## Setup
```shell
Tomas# pip3 install cython
Collecting Cython
Downloading Cython-0.29.26-py2.py3-none-any.whl (983 kB)
|████████████████████████████████| 983 kB 1.0 MB/s
Installing collected packages: Cython
Successfully installed Cython-0.29.26
Tomas# ls /usr/lib/python3.8/site-packages
cython.py Cython-0.29.26.dist-info/ Cython/
```
## Cython Hello World

From above figure, .pyx and .py are the source code we need to prepare. And the .pyx will finally turn to .so which can be imported to a pure python code program.
In this example, we will write square and cube function in an extension module in *perfectpower_module.pyx* and call it from the main pure python *main.py*.
- Inputs
1. perfectpower_module.pyx
2. setup.py
3. main.py
- Outputs
- perfectpower_module.so
### Inputs
```cpython=
# 1. perfectpower_module.pyx
import cython
def square(n):
return n*n
def cube(n):
return n*n*n
```
```cpython=
# 2. setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("perfectpower_module.pyx")
)
```
```python=
# 3. main.py
from perfectpower_module import square
from perfectpower_module import cube
if __name__ == '__main__':
print("Going to import function from perfectpower_module")
print("==================================================")
print("9^2 = %d" %square(9))
print("9^3 = %d" %cube(9))
```
### Outputs
Here is the command in shell to compile cython to a dynamic library *.so.
```shell
Tomas# python3 setup.py build_ext --inplace
Compiling perfectpower_module.pyx because it changed.
[1/1] Cythonizing perfectpower_module.pyx
/usr/lib/python3.8/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /root/perfectpower_module.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
running build_ext
building 'perfectpower_module' extension
creating build
creating build/temp.linux-x86_64-3.8
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fomit-frame-pointer -g -fno-semantic-interposition -fomit-frame-pointer -g -fno-semantic-interposition -fomit-frame-pointer -g -fno-semantic-interposition -DTHREAD_STACK_SIo
creating build/lib.linux-x86_64-3.8
gcc -shared -Wl,--as-needed -Wl,--as-needed build/temp.linux-x86_64-3.8/perfectpower_module.o -L/usr/lib -o build/lib.linux-x86_64-3.8/perfectpower_module.cpython-38-x86_64-linux-gnu.so
copying build/lib.linux-x86_64-3.8/perfectpower_module.cpython-38-x86_64-linux-gnu.so ->
Tomas# ls
main.py
perfectpower_module.cpython-38-x86_64-linux-gnu.so
perfectpower_module.c
perfectpower_module.pyx
setup.py
```
And then it generate two files, *perfectpower_module.cpython-38-x86_64-linux-gnu.so* and *perfectpower_module.c* respectively.
And now, we are going to import functions from *perfectpower_module.cpython-38-x86_64-linux-gnu.so* in our main python program and execute it getting outputs as show below.
```shell
Tomas# python3 main.py
Going to import function from perfectpower_module
==================================================
9^2 = 81
9^3 = 729
```
## Annex
Here shows the intermediate c code from cython.
{%gist e1a4e7bcaae1489d0d0611bd3567084e%}
## Reference
https://prepinsta.com/python/what-is-cpython/
https://en.wikipedia.org/wiki/Cython
https://stackoverflow.com/questions/11436484/how-to-protect-and-compile-python-source-code-into-a-so-library
https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html