Llamar a funciones de C en Python


Tengo un montón de funciones que he escrito en C y me gustaría algún código que he escrito en Python para poder acceder a esas funciones.

He leído varias preguntas aquí que tratan de un problema similar ( aquí y aquí por ejemplo) pero estoy confundido sobre 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 completamente claro cuál será mejor para mí.

Básicamente he escrito código python para hacer FFTs bidimensionales y me gustaría que el código C fuera capaz de ver ese resultado y luego procesarlo a través de las diversas funciones de C que he escrito. No se si será mas fácil para mi llamar a Python desde C o viceversa.

Author: Community, 2013-05-20

4 answers

Si entiendo bien, no tiene preferencia para dialogar como c => python o como python => c. En ese caso yo recomendaría Cython. Está bastante abierto a muchos tipos de manipulación, especialmente, en su caso, llamar a una función que ha sido escrita en Python desde C.

Así es como funciona (public api) :

El siguiente ejemplo asume que tiene una clase Python (self es una instancia de la misma), y que esta clase tiene un método (name method) al que desea llamar esta clase y tratar con el resultado (aquí, un double) de C. Esta función, escrita en un Cython extension le ayudaría 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 de la siguiente manera:

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 un struct proporcionado por Python / C API Después de haber capturado el py_obj (lanzando un python regular object, en su extensión cython como esta: <PyObject *>my_python_object), finalmente sería capaz de llamar al método initSimulation en él y hacer algo con el resultado. (Aquí un double, pero Cython puede tratar fácilmente con vectors, sets, ...)

Bueno, soy consciente de que lo que acabo de escribir puede ser confuso si nunca escribiste nada usando Cython, pero pretende ser una breve demostración de las numerosas cosas que puede hacer por ti en términos de fusión.

Por otro lado, este enfoque puede tomar más tiempo que recodificar su código 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...

 7
Author: Gauthier Boaglio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-20 15:46:30

Debes llamar a C desde Python escribiendo un wrapper 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:

  1. Escriba las funciones de C que desea utilizar. (Probablemente ya lo hiciste)
  2. Crear un objeto compartido (. so, para linux, os x, etc.) o biblioteca cargada dinámicamente (.dll para windows) para esas funciones. (Tal vez usted ya hizo esto, también)
  3. Escribe el ctypes wrapper (Es más fácil de lo que parece, Escribí un how-to para eso)
  4. Llama a una función desde ese contenedor en Python. (Esto es tan simple como llamar a cualquier otra función de python)
 45
Author: Florian Rhiem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-20 06:32:34

Bueno, aquí te estás refiriendo a dos cosas más abajo.

  1. Cómo llamar a la función c dentro de python (Extendiendo python)
  2. Cómo llamar a la función/script de python desde el programa C (Incrustar Python)

Para #2 eso 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 #1 eso es 'Extendiendo Python' Entonces la mejor apuesta sería utilizar Ctypes (btw portable a través de toda la variante de python).

Desde la importación de ctypes *

Libc = cdll.msvcrt

Imprimir libc.tiempo(Ninguno)

1438069008

Printf = libc.printf

Printf ("Hello, %s\n", " World!")

¡Hola, Mundo! 14

Printf ("%d botellas de cerveza\n", 42)

42 botellas de cerveza 19

Para obtener una guía detallada, puede consultar mi blog artículo:

 3
Author: Jadav Bheda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-28 06:44:22

Será más fácil llamar a C desde python. Su escenario suena raro-normalmente la gente escribe la mayor parte del código en python, excepto por la parte intensiva en procesador, que está escrita en C. ¿Es la FFT bidimensional la parte computacionalmente intensiva de su código?

 1
Author: xuanji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-20 10:44:23