ctypes – principiante

Tengo la tarea de “envolver” una biblioteca de ac en una clase de python. Los documentos son increíblemente vagos en este asunto. Parece que esperan que solo los usuarios avanzados de python implementen ctypes. Bueno, yo soy un principiante en python y necesito ayuda.

Un poco de ayuda paso a paso sería maravilloso.

Así que tengo mi biblioteca c. ¿Qué debo hacer? ¿Qué archivos pongo dónde? ¿Cómo importo la biblioteca? ¿Leí que podría haber una manera de “envolver automáticamente” a Python?

(Por cierto, hice el tutorial de ctypes en python.net y no funciona. Lo que significa que estoy pensando que están asumiendo que debería poder completar el rest de los pasos).

De hecho este es el error que obtengo con su código:

File "importtest.py", line 1 >>> from ctypes import * SyntaxError: invalid syntax 

Realmente podría usar un poco de ayuda paso a paso en esto! Gracias ~

Related of "ctypes – principiante"

Aquí hay un tutorial rápido y sucio de ctypes.

Primero, escribe tu biblioteca C Aquí hay un ejemplo simple de Hello World:

testlib.c

 #include  void myprint(void); void myprint() { printf("hello world\n"); } 

Ahora compílalo como una biblioteca compartida ( solución mac encontrada aquí ):

 $ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c # or... for Mac OS X $ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c 

Luego, escribe un envoltorio usando ctypes:

testlibwrapper.py

 import ctypes testlib = ctypes.CDLL('/full/path/to/testlib.so') testlib.myprint() 

Ahora ejecútalo:

 $ python testlibwrapper.py 

Y deberías ver la salida.

 Hello world $ 

Si ya tiene una biblioteca en mente, puede omitir la parte que no es de python del tutorial. Asegúrese de que ctypes pueda encontrar la biblioteca colocándola en /usr/lib u otro directorio estándar. Si hace esto, no necesita especificar la ruta completa al escribir el contenedor. Si elige no hacer esto, debe proporcionar la ruta completa de la biblioteca cuando llame a ctypes.CDLL() .

Este no es el lugar para un tutorial más completo, pero si solicita ayuda con problemas específicos en este sitio, estoy seguro de que la comunidad lo ayudará.

PD: ctypes.CDLL('libc.so.6') que estás en Linux porque has usado ctypes.CDLL('libc.so.6') . Si estás en otro sistema operativo, las cosas pueden cambiar un poco (o bastante).

La respuesta de Chinmay Kanchi es excelente, pero quería un ejemplo de una función que pase y devuelva variables / arrays a un código C ++. Pensé que lo incluiría aquí en caso de que sea útil para otros.

Pasando y devolviendo un entero

El código C ++ para una función que toma un número entero y agrega uno al valor devuelto,

 extern "C" int add_one(int i) { return i+1; } 

Guardado como archivo test.cpp , tenga en cuenta la “C” externa requerida (esto puede eliminarse para el código C). Esto se comstack usando g ++, con argumentos similares a la respuesta de Chinmay Kanchi,

 g++ -shared -o testlib.so -fPIC test.cpp 

El código de Python utiliza load_library del numpy.ctypeslib asumiendo la ruta a la biblioteca compartida en el mismo directorio que el script de Python,

 import numpy.ctypeslib as ctl import ctypes libname = 'testlib.so' libdir = './' lib=ctl.load_library(libname, libdir) py_add_one = lib.add_one py_add_one.argtypes = [ctypes.c_int] value = 5 results = py_add_one(value) print(results) 

Esto imprime 6 como se esperaba.

Pasando e imprimiendo una matriz

También puede pasar matrices de la siguiente manera, para que un código C imprima el elemento de una matriz,

 extern "C" void print_array(double* array, int N) { for (int i=0; i 

que se comstack como antes y se importa de la misma manera. El código extra de Python para usar esta función sería,

 py_print_array = lib.print_array py_print_array.argtypes = [ctl.ndpointer(np.float64, flags='aligned, c_contiguous'), ctypes.c_int] A = np.array([1.4,2.6,3.0], dtype=np.float64) py_print_array(A, 3) 

donde especificamos la matriz, el primer argumento para print_array , como un puntero a una matriz Numpy de flotadores de 64 bits alineados, c_contiguos y el segundo argumento como un entero que le dice al código C el número de elementos en la matriz Numpy. Esto luego impreso por el código C de la siguiente manera,

 1.4 2.6 3.0 

En primer lugar: el código >>> que ves en los ejemplos de python es una forma de indicar que es un código de Python. Se utiliza para separar el código de Python de la salida. Me gusta esto:

 >>> 4+5 9 

Aquí vemos que la línea que comienza con >>> es el código de Python, y 9 es el resultado. Así es como se ve si inicia un intérprete de Python, por lo que se hace así.

Nunca ingresas la parte >>> en un archivo .py .

Eso se encarga de su error de syntax.

En segundo lugar, ctypes es solo una de las varias formas de envolver bibliotecas de Python. Otras formas son SWIG , que analizará su biblioteca de Python y generará un módulo de extensión de Python C que expone la API de C. Otra forma es usar Cython .

Todos ellos tienen ventajas y desventajas.

SWIG solo expondrá su API C a Python. Eso significa que no obtienes ningún objeto ni nada, tendrás que hacer un archivo de Python separado haciendo eso. Sin embargo, es común tener un módulo llamado “wowza” y un módulo SWIG llamado “_wowza” que es el contenedor alrededor de la API de C. Esta es una forma agradable y fácil de hacer las cosas.

Cython genera un archivo de C-Extension. Tiene la ventaja de que todo el código Python que escribes se convierte en C, por lo que los objetos que escribes también están en C, lo que puede ser una mejora de rendimiento. Pero tendrás que aprender cómo interactúa con C, por lo que es un poco más de trabajo aprender a usarlo.

ctypes tiene la ventaja de que no hay código C para comstackr, por lo que es muy agradable de usar para envolver bibliotecas estándar escritas por otra persona, y ya existe en versiones binarias para Windows y OS X.