2012-07-28 23 views
19

he encontrado respuestas parciales entre los documentos, listas de correo, y this question here, pero quería obtener una respuesta más directa frente a mis detalles ...estructura del proyecto para envolver muchas clases ++ c en Cython a un objeto compartido sola

Estoy aprendiendo cython tratando de envolver partes pequeñas, poco a poco, de una biblioteca que ya estoy usando que actualmente está envuelta en boost :: python. He contribuido un poquito a este wrapper boost, y lo estoy usando como referencia de C++, mientras que al mismo tiempo estoy usando ZeroMQ Python bindings como referencia de cython.

Mi pregunta es acerca de la estructura del proyecto. La versión actual de este lib compila a un solo .so, y ese es mi objetivo. Descubrí rápidamente que no se pueden compilar directamente múltiples módulos .pyx en un solo .so. Luego comencé a seguir la ruta de definición de los archivos cppclass en pxd, y sus correspondientes clases de implementación exportadas en python en .pxi, y estaba tratando de incluirlos en un único pyx para la compilación. Si bien funcionó al principio, una vez que escribí un poco más me tocó problemas con definiciones múltiples en conflicto debido a que el pxi incluye en diferentes lugares.

Me gustaría escuchar un enfoque organizacional adecuada que responda a las siguientes preguntas y objetivos:

  • Denominación de las clases públicas el mismo que el cppclass (que estoy haciendo esto ahora por tener el cppclass en un diferente nombre pyd y utilizando el espacio de nombres importados para manejar los nombres similares, ala Using cimport to resolve naming conflicts)
  • individual .so como la salida compilada (acceptable approach?)
  • puedo utilizar la pyx múltiples incluyen enfoque en el principal pyx para eso solo, o debería ese principal pyx contener algo más aparte de solo sostener los includes?
  • ¿Dónde definir centralmente las constantes que se exportarán en python?
  • ¿Existe una estructura de carpetas preferida? En este momento tengo todo en un gran directorio src debajo de mi setup.py. Se vuelve confuso ver tantos archivos pxi, pxd, pyx.
  • ¿Son pxi completamente innecesarios ahora? Si no es así, ¿necesito usar un ifndef guard de estilo cython para manejar las inclusiones múltiples entre diferentes módulos?
  • Sé que los enlaces python ZeroMQ compilan varios módulos y usan el enfoque de paquete incluyéndolos en __init__.py. ¿Es realmente el enfoque adecuado con cython?

Como referencia, el proyecto que estoy practicando para volver a envolver es PyOpenNI (openni). El patrón que este proyecto de impulso requiere es recopilar los objetos comunes en un lugar, y luego definir una definición de encabezado 1-a-1 con el origen, y luego hay un envoltorio enorme que recopila todas las definiciones en una sola ubicación. Y también el manejo y las utilidades de excepciones personalizadas adicionales.

Respuesta

20

Mientras esperaba una respuesta definitiva, seguí jugando con la organización de mi código. La inclusión de archivos pyx en un único pyx para compilación ha estado funcionando hasta el momento.

Mi setup.py es tan simple como:

ext_modules = [ 
    Extension(
     "openni", 
     ["src/openni.pyx"], 
     language="c++", 
     include_dirs=['src/', '/usr/include/ni'], 
     libraries=['OpenNI'], 
    ) 
], 

La principal openni.pyx parece:

include "constants.pyx" 
include "exceptions.pyx" 
include "context.pyx" 
... 

Tengo un libopenni.pxd común para proporcionar sólo de declaración de los externos al resto de los módulos.

nombro mi cppclass de declaraciones pxd un nombre diferente que las definiciones de clase pyx para evitar la colisión de nombres:

xncontext.pxd

cdef extern from "XnCppWrapper.h" namespace "xn": 
    cdef cppclass Context: 
      ... 

context.pyx:

from libopenni cimport * 
from xncontext cimport Context as c_Context 

cdef class Context: 
    cdef c_Context *handle 
     ... 
+0

¿Puedes indicar el resto del código que has creado para este envoltorio? Me encuentro con un problema similar con una resolución similar. No es agradable, pero funciona. – ibell

+2

Oye. Entonces esto no fue algo que terminó en un repositorio público. La mayoría de mis últimos ejemplos de esta estructura no están en línea, pero he aquí uno que hice poco después: https: //github.com/chadmv/plow/tree/master/lib/python/src – jdi

+2

Lo que hago ahora es Mantenga los archivos pxi dentro e incluya el subdirectorio para hacerlo limpio. Y solo tengo el pyx principal encima, junto con el pxd que contiene todas las declaraciones externas para enlazar con el C/CPP – jdi

0

Answeri ng ¿Hay una estructura de carpetas preferida?

Sí, la estructura de carpetas preferido para .pyx y .pxd archivos de Cython es tratarlos exactamente como lo haría con sus .py archivos: uno por cada módulo, en una estructura de paquete bien organizado. Los archivos __init__.pxd se pueden proporcionar como los archivos __init__.py para ensamblar un conjunto de símbolos seleccionados para recopilar un conjunto de símbolos seleccionados de sus submódulos/paquetes para cimportar.

Es cierto que esto produce un archivo .so por módulo, pero estos archivos están ocultos en el directorio de compilación. Lo mismo es cierto para los módulos de construcción de Python; hay un archivo correspondiente .so para cada uno de ellos. ¿Es esto un problema?

+0

Desde hace poco he convertido a un enfoque multi e importándolos en un único espacio de nombres a través de __init__. py – jdi

+0

No sabía que un __init __. pxd tenía importancia en el nivel de módulo – jdi

+0

. Los archivos .so separados para cada módulo pueden ser un problema si aplica una licencia (protección) a esos archivos .so cuando la licencia demora un tiempo en inicializarse . –

Cuestiones relacionadas