Voici un petit exemple, mais complète de tableaux de passage numpy à une fonction externe C, logiquement
fc(int N, double* a, double* b, double* z) # z = a + b
utilisant Cython. (Ceci est certainement bien connu pour ceux qui le connaissent bien commentaires sont les bienvenus Dernière modification:... 23 février 2011, pour Cython 0,14)
Première lecture ou écrémé Cython build et Cython with NumPy.
deux étapes:
python f-setup.py build_ext --inplace
spires f.pyx
et fc.cpp
->f.so
, une bibliothèque dynamique
python test-f.py
import f
charges f.so
; f.fpy(...)
appelle le C fc(...)
.
python f-setup.py
utilise distutils
pour exécuter cython, compiler et lien:
cython f.pyx -> f.cpp
compilez f.cpp
et fc.cpp
lien f.o fc.o
->f.so
, une dynamique lib python import f
chargera.
Pour les étudiants, je suggère: faire un diagramme de ces étapes, regarder à travers les fichiers ci-dessous, puis téléchargez et exécutez-les.
(distutils
est un énorme paquet, alambiqué utilisé pour fabriquons des emballages en Python pour la distribution, et les installer. Ici nous utilisons juste une petite partie de compiler et lien vers f.so
. Cette étape n'a rien à voir avec Cython, mais il peut être source de confusion,.. simples erreurs dans un .pyx peut provoquer des pages de messages d'erreur obscurs de g ++ compiler et lier Voir aussi distutils doc et/ou SO questions on distutils)
Comme make
, setup.py
réexécutera cython f.pyx
et g++ -c ... f.cpp
si f.pyx
est plus récent que f.cpp
.
Pour le nettoyage, rm -r build/
.
Une alternative à setup.py
serait d'exécuter les étapes séparément, dans un script ou 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
.
Modifier le cc-lib-mac
emballage ci-dessous pour votre plate-forme et l'installation: ce n'est pas joli, mais petit.
Pour de vrais exemples de C Cython C, regarder les fichiers .pyx dans à peu près tous SciKit. Voir également: Cython for NumPy users et SO questions/tagged/cython.
Pour décompresser les fichiers suivants, par copier-coller le lot à un gros fichier, dire cython-numpy-c-demo
, puis sous Unix (dans un nouveau répertoire propre) exécuter 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
Je viens Enveloppé ma bibliothèque C en utilisant Cython, vous voudrez peut-être prendre Regardez cela pour un exemple sur la façon de le faire. J'ai expliqué tout le processus en détail ici, y compris la construction et la distribution du module: http://martinsosic.com/development/2016/02/08/wrapping-c-library-as-python-module.html. – Martinsos