Использование Numpy C api в C-расширении для Python

Ниже рассмотрен пример использования Numpy C api при написании расширения для Python на языке C. Расширение будет подключаться с помощью distutils. В примере умножаются поэлементно два массива.

Среда:

  • Linux
  • Python 3.5
  • IPython

Ниже C-код расширения и комментарии. Пояснения размещены под кодом.

[code c]

[/code]
файл numpy_multiply.c

В начале файла, по рекомендации разработчика Numpy, отключаем обратную совместимость со старой версией Numpy C api. Это позволит писать актуальный код и сократить проблемы в будущем:

[code c]

[/code]

В начале функции [code]py_multiply()[/code] получаем numpy-массивы автоматически проверяя тип полученных переменных инструкцией [code c]»O!»[/code] и на выходе имея переменную с типом [code]PyArrayObject[/code].

Ниже представлены примеры с бросанием исключения в Python при неверном измерении и разных размерах массивов.

Ближе к концу, создаем пустой массив размера, равного одному из входящих массивов и заполняем его нулями. При создании массива для полученного объекта счетчик внешних ссылок автоматически приравнивается 1.

Теперь в цикле умножаем элементы массивов. Этот участок кода можно реализовать как угодно в рамках правил языка C.

Возвращаем полученный массив с инструкцией [code с]»N»[/code], это означает, что при передаче объекта мы не будем увеличивать количество ссылок на него. В случае использования инструкции [code c]»O»[/code] можно легко получить утечку памяти, так как количество ссылок будет увеличено на 1 и этот счетчик уже никто не обнулит.

IPython

Все дальнейшие действия выполняются в IPython. Каждый кусок кода вставляем в отдельные ячейки.

Создаем python-скрипт [code]setup_numpy_multiply.py[/code] для компиляции библиотеки в python-пакет.

[code python]

[/code]
ipython, ячейка 1

Запускаем созданный на предыдущем шаге файл [code]setup_numpy_multiply.py[/code] для компиляции в текущую директорию C-библиотеки.

[code python]

[/code]
ipython, ячейка 2

Подключаем модуль и тестируем.

[code python]

[/code]
ipython, ячейка 3

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