python - lista - ¿Es posible autogenerar enlaces de Cython alrededor de una gran biblioteca de C existente?
lista de modulos de python (1)
Me parece ctypesgen ideal para la autogeneración. Solo lo estoy usando con uno o dos módulos de python que espero abrir de código fuente, y hasta ahora he sido feliz. Aquí hay un ejemplo rápido de cómo usarlo con zlib, pero también lo probé con éxito con algunas otras bibliotecas:
(Edit: Sé que mencionaste que ctypesgen tiene problemas en una mac, así que tal vez necesite que alguien la modifique para que funcione en OSX. No tengo OSX en casa o lo intentaría).
Obtener ctypesgen:
git clone https://github.com/davidjamesca/ctypesgen.git
Ejecute un script corto para llamar a ctypesgen (reemplace la información de zlib con otra biblioteca):
import os
ZLIB_INC_DIR = "/usr/include"
ZLIB_LIB_DIR = "/usr/lib/x86_64-linux-gnu"
ZLIB_LIB = "libz.so"
ZLIB_HEADERS = "/usr/include/zlib.h"
# Set location of ctypesgen.py
ctypesgen_path = ''ctypesgen/ctypesgen.py''
wrapper_filename = ''zlib.py''
cmd = "LD_LIBRARY_PATH={} {} -I {} -L {} -l {} {} -o {}".format(
ZLIB_LIB_DIR, ctypesgen_path, ZLIB_INC_DIR, ZLIB_LIB_DIR, ZLIB_LIB,
ZLIB_HEADERS, wrapper_filename)
print(cmd)
os.system(cmd)
Ejemplo de uso:
python
>>> import zlib
>>> zlib.compress("asdfasdfasdfasdfasdf")
''x/x9cK,NIKD/xc3/x00T/xfb/x08/x17''
En otras palabras: *.h/*.c --[??POSSIBLE??]--> *.pxd/*.pyx
DE ACUERDO. He hecho (espero) investigar bastante en Internet, pero creo que esta es una buena pregunta, así que la haré directamente.
Hay algunas preguntas relacionadas (p. Ej., Generar enlaces de Python, qué métodos / programas usar o Ajustar una biblioteca de C en Python: C, Cython o ctypes ) pero que no resumen la situación que estoy preguntando cuál es quizás para un enfoque más "de alto nivel" (y específicamente para una biblioteca existente, no generar nueva C desde python).
Tengo un poco de experiencia con esto, ya que envolví un poquito de código antes de usar Cython. Cython está a la altura de la velocidad y la capacidad de mantenimiento. Eso está bien en mi libro para bits pequeños / únicos de código, pero, esta vez tengo un poco más en mi plato ...
Y siguiendo la primera de las tres grandes virtudes de un programador , quiero hacer esto con el mínimo esfuerzo posible.
Entonces, la pregunta real aquí es cómo puedo facilitar la creación mediante los medios automatizados de los archivos .pxd y posiblemente .pyx (es decir, para ahorrar tiempo y no cometer errores al escribir algo).
Este aquí parece ser el único indicio / nota real sobre cómo hacer esto, pero la mayoría de los proyectos en él son obsoletos, antiguos o de forjado de fuentes. Muchos solo parecen funcionar para C ++ (esto es C que estoy haciendo aquí).
¿Alguien todavía los usa? ¿Recientemente? ¿Alguien tiene un flujo de trabajo o una mejor práctica para hacer esto? ¿Simplemente estoy mejor haciéndolo a mano?
Mi biblioteca está bien definida por un conjunto de archivos de encabezado. Una que contiene las definiciones de todos los C struct / types y otra que contiene prototipos para todas las funciones. Pero es loooonnnggg ...
Gracias por cualquier consejo.
ACTUALIZACIÓN (25 de agosto de 2015):
Correcto, así que en los últimos meses, cuando tuve un momento libre, intenté:
CFFI (gracias por @David que lo señala): tiene el noble objetivo de "llamar al código C de Python sin aprender un tercer idioma: las alternativas existentes requieren que los usuarios aprendan un idioma específico del dominio (Cython, SWIG) o API (ctypes)" - pero no se ajustaba a la medida, ya que implicaba un grado considerable de código C incorporado en los archivos de python reales (o cargarlo). Este sería un proceso bastante manual para una gran biblioteca. Tal vez me perdí algo ...
SWIG es el abuelo de la unión de Python, y es bastante sólido. Fundamentalmente, sin embargo, no es "manos libres" como lo entiendo, es decir, necesita un archivo de especificaciones por separado. Por ejemplo, debe editar todos los archivos de encabezado de C para indicar la creación de un módulo de Python con
#define SWIG_FILE_WITH_INIT
o usar otras anotaciones. SIP tiene el mismo problema aquí. No se genera automáticamente a partir de los encabezados, los modifica para incluir sus propias directivas y anotaciones y crea un archivo de especificación completo.cwrap - Estoy en una Mac, así que usé esta versión para clang. https://github.com/geggo/cwrap Doc. realmente pobre, pero al usar la fuente finalmente pude ejecutarlo y se generó ... un archivo .pyx vacío de un encabezado bastante simple de estructuras. No tan bien.
xdress - Esto se mostró prometedor. El sitio web está caído, por lo que los documentos parecen estar here . Se ha realizado una cantidad impresionante de trabajo y parece fácil de usar. Pero necesitaba todos los encabezados llvm (y una versión correctamente vinculada de clang). Tuve que usar
brew install llvm —with-clang
. Hay una rama declang-3.5
, pero no parece haber hecho suficientes correcciones. Intenté hacer tapping en homebrew / versiones para una versión anterior de clang (instale llvm33 / llvm34) y eso se construyó. De todos modos, estoy divagando ... funcionó muy bien para un ejemplo simple, pero los archivos de ctypes resultantes para la biblioteca completa estaban bastante confusos y se negaron a construir. Algo en el AST C-> Python está un poco mal ...ctypesgen no era uno que había encontrado en la búsqueda original. La documentación es bastante escasa, o podría llamarlo conciso. Aparentemente, tampoco se le ha hecho mucho trabajo en los últimos 4 años (y las personas que preguntan en la lista de problemas si los desarrolladores alguna vez van a promover el proyecto). He intentado ejecutarlo, pero, lamentablemente, parece haber fallado con lo que sospecho / parece que hay problemas con el compilador Clang. Cdefs.h uso de
_attribute_
. He intentado cosas como-std=c11
pero sin éxito.
En conclusión, de todos los que he mirado, creo que la dirección más cercana a la generación totalmente automática de enlaces de python. Funcionó bien para los ejemplos simples dados, pero no pudo manejar los encabezados de biblioteca existentes más complejos, con todas las complejidades de las declaraciones adelantadas, los tipos enumerados, los punteros vacíos ... Parece un proyecto bien diseñado y (por un tiempo) bien mantenido, por lo tanto, es posible que haya alguna forma de evitar estos problemas si alguien se lo vuelve a hacer.
Aún así, la pregunta sigue siendo: ¿Alguien tiene una cadena de herramientas robusta para generar envoltorios Python a partir de encabezados C de forma automática? Creo que la realidad es que siempre tiene que haber un poco de trabajo manual, y para eso CFFI parece ser el enfoque más "moderno" (uno de los mejores resúmenes y comparaciones que he encontrado here ), aunque siempre implica un cdef()
especialmente editado cdef()
versión de cualquier archivo de encabezado (por ejemplo, utilizando CFFI de Python y excluyendo los encabezados del sistema ).