Cython и C++ в IPython

В прошлом посте было описано подключение библиотеки на С. Здесь же представлен код для подключения библиотеки на C++. Преимущества C++ очевидны, поддержка классов, множество шаблонов и других улучшений, о которых лучше всего расскажет Вики.

За основу берем:

  • Linux
  • Python 3.5
  • Ipython (Jupyter Notebook)
  • Файл с кодом на C++

Первым делом определяем директорию и создаем новый блокнот IPython. В эту директорию кладем файл cpp.cpp с кодом на C++.

#include <iostream>
#include <sstream>

using namespace std;

static string inside_c(string s)
{
    ostringstream stringStream;
    string r;

    // create new string
    stringStream << "we get: " << s;
    r = stringStream.str();

    return r;
}

файл cpp.cpp, код на C++

Далее будем работать в блокноте Ipython и все куски кода вставляем в отдельные ячейки. Включаем cython-магию в ipython.

 %cython

ipython, ячейка 1

Создаем файл cpp_call.pyx с заголовком функции из C++. Теперь, так как мы будет кидать туда-сюда строку, подключим необходимый класс из C++.

%%writefile cpp_call.pyx
from libcpp.string cimport string  # include string class from C++
cdef extern from "cpp.cpp":
    cpdef string inside_c(string)

ipython, ячейка 2

Создаем python-скрипт setup_cpp.py для компиляции библиотеки и заголовочного файла в python-пакет. Здесь необходимо указать язык подключаемой библиотеки, чтобы был использован нужный компилятор.

%%writefile setup_cpp.py
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension('cpp_call', sources = ['cpp_call.pyx', 'cpp.cpp'], language="c++")
setup(name="C++ Call", ext_modules = cythonize([ext]))

ipython, ячейка 3

Запускаем созданный на предыдущем шаге файл setup_cpp.py для компиляции в текущую директорию C++-библиотеки вместе с заголовочным файлом и оберткой от Cython.

%%bash
python setup_cpp.py build_ext --inplace

ipython, ячейка 4

Импортируем получившийся класс и вызываем C++-функцию.

import cpp_call # import pyx-file which has our c-library
income = cpp_call.inside_c(b"from python") # send bytes, not string
income # get bytes

ipython, ячейка 5

Репозиторий с кодом.