Appeler les fonctions C en Python

j'ai un tas de fonctions que j'ai écrites en C et j'aimerais qu'un code que j'ai écrit en Python puisse accéder à ces fonctions.

j'ai lu plusieurs questions ici qui traitent d'un problème similaire ( ici et ici par exemple) mais je suis confus sur l'approche que je dois prendre.

une question recommande des ctypes et une autre recommande cython. J'ai lu un peu de la documentation pour les deux, et je ne suis pas du tout sûr de savoir laquelle sera la plus efficace pour moi.

en gros, j'ai écrit un code python pour faire des FFTs bidimensionnels et j'aimerais que le code C puisse voir ce résultat et ensuite le traiter à travers les différentes fonctions C que j'ai écrites. Je ne sais pas si ce sera plus facile pour moi d'appeler le Python de C ou vice versa.

21
demandé sur Community 2013-05-20 14:11:38

4 réponses

si je comprends bien, vous n'avez aucune préférence pour dialoguer comme c => python ou comme python => C. Dans ce cas, je recommande Cython . Il est tout à fait ouvert à toutes sortes de manipulations, spécialement, dans votre cas, appelant une fonction qui a été écrite en Python à partir de C.

Voici comment ça marche ( public api ) :

l'exemple suivant suppose que vous avez une classe Python ( self est exemple de cela), et que cette classe a une méthode (nom method ) vous voulez faire appel à cette classe et traiter le résultat (ici, un double ) de C. Cette fonction, écrite dans un Cython extension vous aiderait à faire cet appel.

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

du côté C, vous pourrez alors exécuter l'appel comme ceci:

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;
}

PyObject est un struct fourni par Python / C API Après avoir pris le py_obj (en moulant un python régulier object , dans votre extension cython comme ceci: <PyObject *>my_python_object ), vous pourriez finalement appeler la méthode initSimulation et faire quelque chose avec le résultat. (Ici un double , mais Cython peut traiter facilement avec vectors , sets , ... )

Eh bien, je suis conscient que ce que je viens d'écrire peut être déroutant si vous n'avez jamais écrit quelque chose en utilisant Cython , mais il vise à être un court démonstration des nombreuses choses qu'il peut faire pour vous en terme de fusion .

d'un autre côté, cette approche peut prendre plus de temps que le recodage de votre code Python en C, selon la complexité de vos algorithmes. À mon avis, investir du temps dans L'apprentissage Cython N'est pertinent que si vous prévoyez d'avoir ce genre de besoins assez souvent...

l'Espérance, c'était le moins instructif...

7
répondu Gauthier Boaglio 2013-05-20 15:46:30

vous devez appeler C de Python en écrivant un ctypes wrapper. Cython est pour faire tourner plus rapidement le code de type python, ctypes est pour rendre les fonctions C appelables à partir de python. Ce que vous devez faire est le suivant:

  1. écrivez les fonctions C que vous voulez utiliser. (Vous l'avez probablement déjà fait)
  2. crée un objet partagé (.donc, pour linux, os x, etc) ou une bibliothèque chargée dynamiquement (.dll pour windows) pour ceux fonction. (Peut-être l'avez-vous déjà fait aussi)
  3. Écriture de la ctypes emballage (C'est plus facile qu'il n'y paraît, j'ai écrit un how-to pour qui )
  4. appelle une fonction de ce wrapper en Python. (C'est aussi simple que d'appeler n'importe quelle autre fonction python)
45
répondu Florian Rhiem 2015-02-20 06:32:34

eh Bien, ici, vous faites référence à deux choses ci-dessous.

  1. Comment appeler c de la fonction au sein de python (Extension de python)
  2. comment appeler la fonction python / le script à partir du programme C (Embedding Python)

#2 d '"Intégration Python'

vous pouvez utiliser le segment de code ci-dessous:

#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; }

#1 'Extension de Python' Le meilleur pari serait alors d'utiliser des Ctypes (btw portable à travers toutes les variantes de python).

de ctypes import *

libc = cdll.msvcrt

impression de la libc.temps(Aucun)

1438069008

printf = libc.printf

printf("Bonjour %s\n", "le Monde!")

Bonjour, Monde! 14

printf ("%d bouteilles de bière\n", 42)

42 bouteilles de bière 19

pour un guide détaillé, vous pouvez vous référer à mon article de blog :

3
répondu Jadav Bheda 2015-08-28 06:44:22

il sera plus facile d'appeler C de python. Votre scénario a l'air bizarre - normalement les gens écrivent la plupart du code en python sauf pour la partie intensive en processeur, qui est écrite en C. Est-ce que le FFT bidimensionnel est la partie intensive en calcul de votre code?

1
répondu xuanji 2013-05-20 10:44:23