tutorial - Usar Cython para vincular Python a una biblioteca compartida
cython install (1)
Estoy tratando de integrar una biblioteca de terceros escrita en C
con mi aplicación de python
usando Cython
. Tengo todo el código de Python escrito para una prueba. Tengo problemas para encontrar un ejemplo para configurar esto.
Tengo un archivo pyd/pyx
que creé manualmente. El tercero me ha dado un header file (*.h)
y una shared library (*.so)
. Por lo que puedo decir, no hay otras dependencias. ¿Alguien puede dar un ejemplo de cómo configurar esto con Cython
y disutils
?
Gracias
Por supuesto !
(En lo que sigue, supongo que ya sabes cómo lidiar con cimport
y las interacciones entre .pxd
y .pyx
. Si esto no es completamente el caso, solo pregunta y desarrollaré esa parte también)
La muestra (tomada de un proyecto mío C ++, pero un proyecto C funcionaría más o menos igual):
1. El archivo de configuración de Distutils:
Suponiendo que la extensión que se creará se llamará myext
y la biblioteca compartida de terceros será libexternlib.so
(tenga en cuenta el prefijo lib * , aquí) ...
# setup.py file
import sys
import os
import shutil
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
# clean previous build
for root, dirs, files in os.walk(".", topdown=False):
for name in files:
if (name.startswith("myext") and not(name.endswith(".pyx") or name.endswith(".pxd"))):
os.remove(os.path.join(root, name))
for name in dirs:
if (name == "build"):
shutil.rmtree(name)
# build "myext.so" python extension to be added to "PYTHONPATH" afterwards...
setup(
cmdclass = {''build_ext'': build_ext},
ext_modules = [
Extension("myext",
sources=["myext.pyx",
"SomeAdditionalCppClass1.cpp",
"SomeAdditionalCppClass2.cpp"
],
libraries=["externlib"], # refers to "libexternlib.so"
language="c++", # remove this if C and not C++
extra_compile_args=["-fopenmp", "-O3"],
extra_link_args=["-DSOME_DEFINE_OPT",
"-L./some/extra/dependency/dir/"]
)
]
)
Nota: Su archivo externo .so
está vinculado a través de la opción de libraries
:
libraries=["externlib"] # Without the ''lib'' prefix and the ''.so'' extension...
Nota: la opción de sources
se puede usar para obtener algunos archivos fuente adicionales compilados.
Importante: myext.pxd
(no confundas con .pyd
- cosas de Windows) y myext.pyx
deberían estar en el mismo directorio. En tiempo de compilación, el archivo de definición, si existe, se procesa primero ( more ).
2. Luego ejecútelo de la siguiente manera:
Después de haber cambiado el directorio al que contiene tu myext.pxd
, tu myext.pyx
, así como el script setup.py
anterior:
# setup.sh
# Make the "myext" Python Module ("myext.so")
CC="gcc" /
CXX="g++" /
CFLAGS="-I./some/path/to/includes/ -I../../../DEPENDENCIES/python2.7/inc -I../../../DEPENDENCIES/gsl-1.15" /
LDFLAGS="-L./some/path/to/externlib/" /
python setup.py build_ext --inplace
Dónde :
- Se supone que
libexternlib.so
se encuentra en./some/path/to/externlib/
- se supone que
yourheader.h
se encuentra en./some/path/to/includes/
Nota: CFLAGS
también podría haberse configurado usando la opción extra_compile_args
:
extra_compile_args=["-I./some/path/to/includes/", "-fopenmp", "-O3"]
Nota: LDFLAGS
también podría haberse configurado usando la opción extra_link_args
:
extra_link_args=["-L./some/path/to/externlib/", "-DSOME_DEFINE_OPT", "-L./some/extra/dependency/dir/"]
Una vez que distutils termina con la construcción, obtienes algunos archivos nuevos, especialmente myext.cpp
, myext.h
y lo más importante, myext.so
.
3. Después de eso, estás listo para ir:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./some/path/to/externlib/
export PYTHONPATH=$PYTHONPATH:./some/path/to/myext/
# Run some script requiring "myext.so"
python somescript.py
Donde su extensión de Python recién creada se puede importar por su nombre:
# somescript.py
import myext
from myext import PySomeFeature
...
Nota acerca de la optimización: de manera predeterminada, se utiliza -O2
para compilar la extensión, pero esta puede estar sobrecargada (consulte la configuración anterior donde se especifica -O3
).
Nota sobre las rutas de Cython: si Cython se instaló en un directorio personalizado, es posible que desee agregarlo a su entorno, antes de todo:
PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18 export PYTHONPATH;
PATH=$PATH:../../../DEPENDENCIES/Cython-0.18/bin; export PATH;
Bueno, espero haber cubierto los puntos principales ...