Вот небольшой, но полный пример прохождения Numpy массивов к внешней функции C, логически
fc(int N, double* a, double* b, double* z) # z = a + b
использованием Cython. (Это, конечно, хорошо известно тем, кто знает его хорошо Комментарии приветствуются Последнее изменение:... 23 февраля 2011, для Cython 0,14)
Первое чтение или обезжиренное Cython build и Cython with NumPy.
2 шага:
python f-setup.py build_ext --inplace
превращает f.pyx
и fc.cpp
->f.so
, динамическая библиотека
python test-f.py
import f
грузы f.so
; f.fpy(...)
называет C fc(...)
.
python f-setup.py
использует distutils
для запуска Cython, компилировать и ссылка:
cython f.pyx -> f.cpp
компилировать f.cpp
и fc.cpp
ссылку f.o fc.o
->f.so
, динамический Lib, что питон import f
загрузит.
Для студентов я предлагаю: составить схему этих шагов, просмотреть файлы ниже, а затем загрузить и запустить их.
(distutils
огромный, запутанный пакет используется для пакетов Python делают для распространения, и установить их. Здесь мы используем лишь малую часть его, чтобы собрать и ссылку на f.so
. Этот шаг не имеет ничего делать с Cython, но это может быть запутанным,.. простые ошибки в .pyx может вызвать страницы непонятных сообщений об ошибках от г ++ компилируется и ссылки Смотрите также distutils doc и/или SO questions on distutils)
Как make
, setup.py
будет повторно запущен cython f.pyx
и g++ -c ... f.cpp
если f.pyx
является новее, чем f.cpp
.
Для очистки, rm -r build/
.
Альтернативой setup.py
будет запускать шаги отдельно, в сценарии или Makefile:
cython --cplus f.pyx -> f.cpp # see cython -h
g++ -c ... f.cpp -> f.o
g++ -c ... fc.cpp -> fc.o
cc-lib f.o fc.o -> dynamic library f.so
.
Измените обертку cc-lib-mac
ниже для вашей платформы и установки: это не красиво, но мало.
Для реальных примеров упаковки Cython C, смотрите .pyx-файлы практически в любом SciKit.
См. Также: Cython for NumPy users и SO questions/tagged/cython.
Чтобы распаковать следующие файлы, вырезать-вставить много в один большой файл, скажем cython-numpy-c-demo
, затем в Unix (в чистом новом каталоге) запустить sh cython-numpy-c-demo
.
#--------------------------------------------------------------------------------
cat >f.pyx <<\!
# f.pyx: numpy arrays -> extern from "fc.h"
# 3 steps:
# cython f.pyx -> f.c
# link: python f-setup.py build_ext --inplace -> f.so, a dynamic library
# py test-f.py: import f gets f.so, f.fpy below calls fc()
import numpy as np
cimport numpy as np
cdef extern from "fc.h":
int fc(int N, double* a, double* b, double* z) # z = a + b
def fpy(N,
np.ndarray[np.double_t,ndim=1] A,
np.ndarray[np.double_t,ndim=1] B,
np.ndarray[np.double_t,ndim=1] Z):
""" wrap np arrays to fc(a.data ...) """
assert N <= len(A) == len(B) == len(Z)
fcret = fc(N, <double*> A.data, <double*> B.data, <double*> Z.data)
# fcret = fc(N, A.data, B.data, Z.data) grr char*
return fcret
!
#--------------------------------------------------------------------------------
cat >fc.h <<\!
// fc.h: numpy arrays from cython , double*
int fc(int N, const double a[], const double b[], double z[]);
!
#--------------------------------------------------------------------------------
cat >fc.cpp <<\!
// fc.cpp: z = a + b, numpy arrays from cython
#include "fc.h"
#include <stdio.h>
int fc(int N, const double a[], const double b[], double z[])
{
printf("fc: N=%d a[0]=%f b[0]=%f \n", N, a[0], b[0]);
for(int j = 0; j < N; j ++){
z[j] = a[j] + b[j];
}
return N;
}
!
#--------------------------------------------------------------------------------
cat >f-setup.py <<\!
# python f-setup.py build_ext --inplace
# cython f.pyx -> f.cpp
# g++ -c f.cpp -> f.o
# g++ -c fc.cpp -> fc.o
# link f.o fc.o -> f.so
# distutils uses the Makefile distutils.sysconfig.get_makefile_filename()
# for compiling and linking: a sea of options.
# http://docs.python.org/distutils/introduction.html
# http://docs.python.org/distutils/apiref.html 20 pages ...
# https://stackoverflow.com/questions/tagged/distutils+python
import numpy
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# from Cython.Build import cythonize
ext_modules = [Extension(
name="f",
sources=["f.pyx", "fc.cpp"],
# extra_objects=["fc.o"], # if you compile fc.cpp separately
include_dirs = [numpy.get_include()], # .../site-packages/numpy/core/include
language="c++",
# libraries=
# extra_compile_args = "...".split(),
# extra_link_args = "...".split()
)]
setup(
name = 'f',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules,
# ext_modules = cythonize(ext_modules) ? not in 0.14.1
# version=
# description=
# author=
# author_email=
)
# test: import f
!
#--------------------------------------------------------------------------------
cat >test-f.py <<\!
#!/usr/bin/env python
# test-f.py
import numpy as np
import f # loads f.so from cc-lib: f.pyx -> f.c + fc.o -> f.so
N = 3
a = np.arange(N, dtype=np.float64)
b = np.arange(N, dtype=np.float64)
z = np.ones(N, dtype=np.float64) * np.NaN
fret = f.fpy(N, a, b, z)
print "fpy -> fc z:", z
!
#--------------------------------------------------------------------------------
cat >cc-lib-mac <<\!
#!/bin/sh
me=${0##*/}
case $1 in
"")
set -- f.cpp fc.cpp ;; # default: g++ these
-h* | --h*)
echo "
$me [g++ flags] xx.c yy.cpp zz.o ...
compiles .c .cpp .o files to a dynamic lib xx.so
"
exit 1
esac
# Logically this is simple, compile and link,
# but platform-dependent, layers upon layers, gloom, doom
base=${1%.c*}
base=${base%.o}
set -x
g++ -dynamic -arch ppc \
-bundle -undefined dynamic_lookup \
-fno-strict-aliasing -fPIC -fno-common -DNDEBUG `# -g` -fwrapv \
-isysroot /Developer/SDKs/MacOSX10.4u.sdk \
-I/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 \
-I${Pysite?}/numpy/core/include \
-O2 -Wall \
"[email protected]" \
-o $base.so
# undefs: nm -gpv $base.so | egrep '^ *U _+[^P]'
!
# 23 Feb 2011 13:38
Я только недавно обернула C библиотека с помощью Cython, вы можете взять посмотрите на пример, как это сделать. Здесь я подробно объяснил весь процесс, включая создание и распространение модуля: http://martinsosic.com/development/2016/02/08/wrapping-c-library-as-python-module.html. – Martinsos