tutorial python c linker cython distutils

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 ...