Cython — python приложение на C

Cython — это язык программирования, который дополняет python возможностью типизированного задания переменных и возможностью компиляции в Си код, который в последствии можно скомпилировать в бинарник.
Python потрясающий язык программирования. Но скорость его выполнения оставляет желать лучшего. И как раз в этом нам может помоч cython. На данный момент он практически без труда умеет компилировать python код в си.

Давайте рассмотрим все на примере.
Вот код python для нахождения чисел Фибаначи.

def fib(n):
        if n==0:
                return 0
        elif n==1:
                return 1
        else:
                return fib(n-1) + fib(n-2)
                
                
result = []
for i in range (30):
        result.append(fib(i))
print result

Ничего сложного. Быстро и удобно. Но сколько времени занимает выполнение?

$ time python fib.py 
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]

real    0m0.933s
user    0m0.926s
sys     0m0.008s

А теперь рассмотрим тот же код cython.

cdef fib(int n):
        if n==0:
                return 0
        elif n==1:
                return 1
        else:
                return fib(n-1) + fib(n-2)
                
                
result = []
for i in range (30):
        result.append(fib(i))
print result

Тот же код, только cdef вместо def и параметр, который передается в функцию помечен как целочисленный.
Скомпилируем этот код в си.

cython -2 --embed fib.pyx -o fib.c

embed — говорит компилятору, генерировать так же код main функции.

Теперь компилируем полученный файл при помощи gcc.

gcc fib.c -o fib `python-config --includes --ldflags`

Запускаем.

$ time ./fib 
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229]

real    0m0.135s
user    0m0.128s
sys     0m0.007s

Как видите, резульат — всем результатам результат!

Кроме того, можно скомпилировать cython модуль в разделяемую библиотеку и импортировать её в интерпритатор python.
Создадим функцию.

def helloFunction ():
    return 'Hello World!'

Компилируем.

cython -2 mycode.pyx -o mycode.c
gcc -g -O2 -shared -o mycode.so mycode.c `python-config --includes --ldflags` -fPIC

Запускаем интерпритатор и пробуем выполнить.

$ python
Python 2.7.8 (default, Nov 10 2014, 08:19:18) 
[GCC 4.9.2 20141101 (Red Hat 4.9.2-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mycode
>>> mycode.helloFunction()
'Hello World!'

А теперь наоборот! Выполняем функцию из C кода.
Создаем файл pyapp.pyx.

def helloFunction():
        return "Hello world!"

cdef public void start_app():
        print helloFunction()

Компилируем.

cython pyapp.pyx -o pyapp.c

Создаем файл main.c

#include <Python.h>
#include "pyapp.h"

int main (int argc, char **argv) 
{
        printf ("Initializing Python Runtime...\n");
        Py_Initialize ();

        /* инициализация нашего приложения */
        initpyapp();
        /* запускаем функцию */
        start_app();

        printf ("Cleanup...\n");
        Py_Finalize ();
        return 0;
}

Компилируем.

gcc -o app main.c pyapp.c `python-config --includes --ldflags`

Запускаем.

$ ./app 
Initializing Python Runtime...
Hello world!
Cleanup...

Сработало. Вот это да.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий