Pregunta

He estado dándole vueltas a escribir un pico de montaje de la biblioteca por un tiempo.Sé Python bastante bien y el plan de aplicación de todo en Python, para empezar, pero se prevé que voy a tener que volver a implementar algún núcleo rutinas en un lenguaje compilado con el tiempo.

Si mal no recuerdo, uno de Python original remite fue como un lenguaje de creación de prototipos, sin embargo Python es bastante liberal en lo que permite funciones, functors, los objetos que se pasan a las funciones y métodos, mientras que sospecho que el mismo no es cierto para decir C o Fortran.

¿Qué debo saber sobre el diseño de funciones/clases que imagino tendrán que tener una interfaz en el lenguaje compilado?Y cuánto de estos potenciales problemas son tratados por las bibliotecas, tales como cTypes, bgen, TRAGO, Boost.Python, Cython o Python SIP?

Para este caso de uso en particular, (una adaptación de la biblioteca) me imagino que permite a los usuarios definir funciones matemáticas (Guassian, Lorenz, etc.) como Python las funciones que puede, a continuación, pasar un interpretada por el código compilado de montaje de la biblioteca.Pasar y devolver arrays, es también esencial.

¿Fue útil?

Solución

Finalmente, una cuestión que no puede realmente poner un valor de respuesta para :).

He investigado f2py, boost.python, trago, cython y de pyrex para mi trabajo (Doctorado en óptica de las técnicas de medición).He utilizado trago ampliamente, boost.python algunos y pyrex y cython mucho.También he usado ctypes.Este es mi análisis:

Descargo de responsabilidad:Esta es mi experiencia personal.Yo no estoy involucrado con cualquiera de estos proyectos.

trago: no juega bien con c++.Debería, pero el nombre de planchado de problemas en la vinculación de paso, fue un gran dolor de cabeza para mí en linux y Mac OS X.Si usted tiene el código C y desea que la interfaz de python, es una buena solución.Me envolvió el GTS para mis necesidades y necesarias para escribir, básicamente, una C de la biblioteca compartida en la que me podía conectar.Yo no lo recomendaría.

Ctypes: Escribí un libdc1394 (IEEE de la Cámara de la biblioteca) contenedor con ctypes y era muy straigtforward experiencia.Usted puede encontrar el código en https://launchpad.net/pydc1394.Es mucho trabajo para convertir los encabezados de código de python, pero luego todo funciona de forma fiable.Esta es una buena manera si desea interfaz de una biblioteca externa.Ctypes es también en el stdlib de python, por lo que todo el mundo puede utilizar el código de inmediato.Esta es también una buena manera de jugar con un nuevo lib en python rápidamente.Se lo recomiendo a la interfaz externa libs.

Boost.Python:Muy agradable.Si usted ya tiene C++ con su propio código que desea utilizar en python, ir a por ello.Es muy fácil de traducir de c++ estructuras de clase en python estructuras de clase de esta manera.Os lo recomiendo si tienes el código de c++ que usted necesita en python.

Pyrex/Cython: Uso Cython, no Pyrex.Período.Cython es más avanzado y más agradable de usar.Hoy en día, todo lo hago con cython que yo solía hacer con TRAGO o Ctypes.También es la mejor manera si tienes el código de python que se ejecuta muy lento.El proceso es absolutamente fantástico:convertir los módulos de python en cython módulos, construir y mantener la creación de perfiles y la optimización como todavía era de python (no hay cambio de herramientas es necesario).A continuación, puede aplicar tanto (o tan poco) código C mezclado con el código de python.Este es por lejos más rápido que tener que reescribir partes enteras de su aplicación en C;usted sólo reescribir el bucle interno.

Los tiempos:ctypes tiene la mayor sobrecarga de la llamada (~700ns), seguido por impulso.python (322ns), y luego directamente por swig (290ns).Cython tiene la menor sobrecarga de la llamada (124ns) y el mejor retroalimentación donde pasa tiempo en (cProfile apoyo!).Los números son de mi cuadro de llamar a un trivial de la función que devuelve un entero de un shell interactivo;el módulo de importación de sobrecarga es, por tanto, no se mide el tiempo, sólo en función de la sobrecarga de la llamada es.Por lo tanto, es más fácil y más productivo para obtener el código de python rápido por los perfiles y el uso de cython.

Resumen:Para su problema, utilice Cython ;).Espero que este resumen va a ser útil para algunas personas.Estaré encantado de responder a cualquier pregunta que queda.


Editar:Se me olvidó mencionar:para numérica de los efectos (es decir, conexión a NumPy) uso Cython;tienen soporte para el mismo (debido a que, básicamente, desarrollar cython para este propósito).Por lo que este debe ser otro +1 para su decisión.

Otros consejos

No he utilizado TRAGO o SIP, pero me parece que la escritura de Python contenedores con boost.python a ser muy potente y relativamente fácil de usar.

No estoy claro en lo que sus necesidades son para pasar entre los tipos de C/C++ y python, pero usted puede hacerlo fácilmente ya sea por la exposición de una de tipos de C++ a python, o mediante el uso de un genérico boost::python::objeto argumento a su API de C++.También puede registrar los convertidores para convertir automáticamente python tipos de C++ tipos y viceversa.

Si usted planea usar el boost.en python, el tutorial es un buen lugar para empezar.

He implementado algo similar a lo que usted necesita.Tengo una función de C++ que acepta una función de python y una imagen como argumentos, y se aplica la función de python para cada píxel de la imagen.

Image* unary(boost::python::object op, Image& im)
{
    Image* out = new Image(im.width(), im.height(), im.channels());
    for(unsigned int i=0; i<im.size(); i++)
    {
        (*out)[i] == extract<float>(op(im[i]));
    }
    return out;
}

En este caso, la Imagen es un objeto de C++ expuestos a python (una imagen con flotador de píxeles), y el op es un python función definida por (o en realidad cualquier objeto de python con un __llamada__ atributo).Usted puede usar esta función de la siguiente manera (suponiendo que unario se encuentra en el llamado imagen, que también contiene la Imagen y una función de carga):

import image
im = image.load('somefile.tiff')
double_im = image.unary(lambda x: 2.0*x, im)

Como para el uso de matrices con boost, yo personalmente no he hecho esto, pero sé que la funcionalidad para exponer las matrices en python usando boost está disponible - este podría ser útil.

La mejor manera de plan para una eventual transición al código compilado es escribir el rendimiento de las partes sensibles como un módulo de funciones simples en un de estilo funcional (apátridas y sin efectos secundarios), que aceptan y devuelven tipos de datos básicos.

Esto proporcionará un uno-a-uno la asignación de sus Python prototipo de código para la eventual código compilado, y que le permitirá usar el ctypes fácilmente y evitar un montón de dolores de cabeza.

Para el pico de montaje, es casi seguro que necesitará el uso de matrices, que va a complicar un poco las cosas, pero todavía es muy factible con ctypes.

Si usted realmente desea utilizar más complicadas estructuras de datos, o modificar los argumentos pasados, TRAGO o Python estándar de C-interfaz de extensión te permitirá hacer lo que quieras, pero con una cierta cantidad de problemas.

Por lo que estás haciendo, puede que también desee comprobar hacia fuera NumPy, que podría hacer algunos de los trabajos que usted quiere empujar a y C, así como la oferta de alguna ayuda adicional en el movimiento de los datos de ida y vuelta entre Python y C.

f2py (parte de numpy) es una alternativa más simple a TRAGO y boost.python para envolver C/Fortran compuadora código.

En mi experiencia, hay dos maneras fáciles de llamada en código C de código de Python.Hay otros enfoques, que son más molestos y/o detallado.

La primera y más sencilla es la de recopilar un montón de código C por separado como una biblioteca compartida y, a continuación, llamar a las funciones de la biblioteca en el uso de ctypes.Por desgracia, pasando de otra cosa que de los tipos de datos básicos es no trivial.

La segunda forma más fácil es escribir un módulo de Python en C y, a continuación, llamar a funciones en ese módulo.Puede pasar cualquier cosa que usted desea para estas funciones de C sin tener que pasar a través de cualquier aros.Y es fácil llamar a Python las funciones o los métodos a partir de estas funciones de C, como se describe aquí: https://docs.python.org/extending/extending.html#calling-python-functions-from-c

No tengo suficiente experiencia con SWIG para ofrecer inteligente comentario.Y mientras que es posible hacer cosas como pasar personalizado de los objetos de Python a C funciones a través de ctypes, o para definir las clases de Python en C, estas cosas son molestas y detallado y yo recomiendo tomar uno de los dos enfoques descritos anteriormente.

Python es bastante liberal en lo que permite funciones, functors, los objetos que se pasan a las funciones y métodos, mientras que sospecho que el mismo no es cierto para decir C o Fortran.

En C no se puede pasar una función como argumento a una función, pero se puede pasar un puntero a función que es tan bueno como una función.

No sé cómo mucho de lo que sería de ayuda cuando usted está tratando de integrar los C y el código de Python, pero sólo quería aclarar un concepto erróneo.

Además de las herramientas mencionadas anteriormente, puedo recomendar el uso de Pyrex (para la creación de módulos de extensión de Python) o Psyco (como compilador JIT para Python).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top