tutorial - programar funciones en python
Llamando funciones C en Python (4)
Tengo un montón de funciones que he escrito en C y me gustaría algún código que haya escrito en Python para poder acceder a esas funciones.
He leído varias preguntas aquí que tratan con un problema similar ( here y here por ejemplo) pero estoy confundido acerca de qué enfoque debo tomar.
Una pregunta recomienda ctypes y otra recomienda cython. He leído un poco de la documentación de ambos, y no estoy del todo claro sobre cuál funcionará mejor para mí.
Básicamente, he escrito algún código de Python para hacer algunos FFT bidimensionales y me gustaría que el código C pudiera ver ese resultado y luego procesarlo a través de las diversas funciones de C que he escrito. No sé si será más fácil para mí llamar a Python desde C o viceversa.
Bueno, aquí te refieres a dos cosas abajo.
- Cómo llamar a la función c desde python (extensión de python)
- Cómo llamar a la función / script python desde el programa C (Incrustar Python)
Para el # 2 que es ''Incrustar Python''
Puede usar el siguiente segmento de código:
#include "python.h"
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime/n"
"print ''Today is'',ctime(time())/n");
/*Or if you want to run python file within from the C code*/
//pyRun_SimpleFile("Filename");
Py_Finalize();
return 0; }
Para el # 1 que es ''Extender Python'', entonces lo mejor sería usar Ctypes (por cierto, portátil en todas las variantes de python).
desde ctypes import *
libc = cdll.msvcrt
imprimir libc.time (Ninguno)
1438069008
printf = libc.printf
printf ("Hola,% s / n", "Mundo!")
¡Hola Mundo! 14
printf ("% d botellas de cerveza / n", 42)
42 botellas de cerveza 19
Para obtener una guía detallada, puede consultar el artículo de mi blog :
Deberías llamar a C desde Python escribiendo un envoltorio ctypes . Cython es para hacer que el código similar a python se ejecute más rápido, ctypes es para hacer que las funciones de C se puedan llamar desde python. Lo que necesitas hacer es lo siguiente:
- Escribe las funciones en C que quieras usar. (Probablemente ya lo hiciste)
- Cree un objeto compartido (.so, para linux, os x, etc.) o una biblioteca cargada dinámicamente (.dll, para Windows) para esas funciones. (Tal vez usted también hizo esto, también)
- Escribe el envoltorio de ctypes (Es más fácil de lo que parece, escribí una guía para eso )
- Llama a una función desde ese contenedor en Python. (Esto es tan simple como llamar a cualquier otra función de Python)
Será más fácil llamar a C desde python. Su escenario suena extraño: normalmente la gente escribe la mayoría del código en python, excepto la parte que requiere un uso intensivo del procesador, que está escrito en C. ¿Es la FFT bidimensional la parte computacionalmente intensiva de su código?
Si entiendo bien, no tiene preferencia por dialogar como c => python o como python => c. En ese caso recomendaría Cython
. Es bastante abierto a muchos tipos de manipulación, especialmente, en su caso, llamando a una función que se ha escrito en Python desde C.
Así es como funciona ( public api
):
El siguiente ejemplo asume que usted tiene una Clase Python ( self
es una instancia de ella), y que esta clase tiene un método ( method
nombre) al que desea llamar en esta clase y lidiar con el resultado (aquí, un double
) de C Esta función, escrita en una Cython extension
le ayudará a hacer esta llamada.
cdef public api double cy_call_func_double(object self, char* method, bint *error):
if (hasattr(self, method)):
error[0] = 0
return getattr(self, method)();
else:
error[0] = 1
En el lado C, entonces podrás realizar la llamada así:
PyObject *py_obj = ....
...
if (py_obj) {
int error;
double result;
result = cy_call_func_double(py_obj, (char*)"initSimulation", &error);
cout << "Do something with the result : " << result << endl;
}
Donde PyObject
es una struct
proporcionada por Python / C API Después de haber capturado el py_obj
(lanzando un object
Python normal, en tu extensión de cython como esta: <PyObject *>my_python_object
), finalmente initSimulation
llamar al método initSimulation
en él Y hacer algo con el resultado. (Aquí un double
, pero Cython puede lidiar fácilmente con vectors
, sets
, ... )
Bueno, soy consciente de que lo que acabo de escribir puede ser confuso si nunca escribiste nada con Cython
, pero pretende ser una breve demostración de las numerosas cosas que puede hacer por ti en el proceso de fusión .
Por otra parte, este enfoque puede llevar más tiempo que la recodificación de su código de Python en C, dependiendo de la complejidad de sus algoritmos. En mi opinión, invertir tiempo en aprender Cython es pertinente solo si planea tener este tipo de necesidades con bastante frecuencia ...
Espero que esto haya sido al menos informativo ...