Вызов функций C в Python

У меня есть куча функций, которые я написал на C, и мне нужен код, написанный на Python, чтобы иметь доступ к этим функциям.

Здесь я прочитал несколько вопросов, которые касаются аналогичной проблемы (здесь и здесь для пример), но я смущен тем, какой подход мне нужен.

Один вопрос рекомендует ctypes, а другой рекомендует cython. Я прочитал немного документации для обоих, и я совершенно не понимаю, о чем я буду работать лучше для меня.

В принципе, я написал код python для выполнения двухмерных БПФ, и я бы хотел, чтобы C-код смог увидеть этот результат, а затем обработать его через различные функции C, которые я написал. Я не знаю, будет ли мне легче называть Python с C или наоборот.

Ответы

Ответ 1

Если я хорошо понимаю, у вас нет предпочтения диалогизировать как c = > python или как python = > c. В этом случае я бы рекомендовал Cython. Он довольно открыт для многих видов манипуляций, особенно в вашем случае, вызывая функцию, написанную на Python с C.

Вот как это работает (public api):

В следующем примере предполагается, что у вас есть класс Python (self - его экземпляр) и что у этого класса есть метод (name method), который вы хотите вызвать в этом классе и обработать результат ( здесь, a double) от C. Эта функция, написанная в Cython extension, поможет вам выполнить этот вызов.

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

На стороне C вы сможете выполнить вызов следующим образом:

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 - это struct, предоставляемый Python/C API После того, как вы поймали py_obj (добавив обычный python object в расширение cython, например: <PyObject *>my_python_object), вы, наконец, сможете вызвать метод initSimulation и сделать что-то с результатом. (Здесь a double, но Cython легко справляется с vectors, sets,...)

Хорошо, я знаю, что то, что я только что написал, может сбивать с толку, если вы никогда ничего не писали, используя Cython, но он должен быть короткой демонстрацией многочисленных вещей, которые он может сделать для вас с точки зрения слияния.

С другой стороны, этот подход может занять больше времени, чем перекодировать ваш код Python на C, в зависимости от сложности ваших алгоритмов. На мой взгляд, время инвестирования в обучение Cython уместно только в том случае, если вы планируете часто получать такие потребности...

Надеюсь, это было хотя бы информативным...

Ответ 2

Вы должны вызвать C из Python, написав обертку ctypes. Cython предназначен для того, чтобы сделать python-подобный код быстрее, ctypes предназначен для выполнения C-функций, вызываемых из python. Что вам нужно сделать, это следующее:

  • Напишите функции C, которые вы хотите использовать. (Возможно, вы уже это сделали)
  • Создайте общий объект (.so, для linux, os x и т.д.) или динамически загружаемую библиотеку (DLL, для Windows) для этих функций. (Возможно, вы уже сделали это тоже)
  • Напишите оболочку ctypes (это проще, чем кажется, Я написал практическое руководство для этого)
  • Вызвать функцию из этой оболочки в Python. (Это так же просто, как вызов любой другой функции python)

Ответ 3

Будет проще вызвать C из python. Ваш сценарий звучит странно - обычно люди пишут большую часть кода в python, за исключением процессорной части, написанной на C. Является ли двумерный FFT вычислительно-интенсивной частью вашего кода?

Ответ 4

Ну, здесь вы имеете в виду две вещи ниже.

  • Как вызвать функцию c внутри из python (Расширение python)
  • Как вызвать функцию python/ script из программы C (Embedding Python)

Для # 2, который является "Встраивание Python"

Вы можете использовать сегмент кода ниже:

#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, который является "Расширением Python" Тогда лучше всего было бы использовать Ctypes (btw portable по всему варианту python).

из импорта ctypes *

     

libc = cdll.msvcrt

     

print libc.time(Нет)

     

1438069008

     

printf = libc.printf

     

printf ( "Привет,% s\n", "Мир!" )

     

Привет, мир!   14

     

printf ( "% d бутылок пива \n", 42)

     

42 бутылки пива   19

Для подробного руководства вы можете обратиться к моей статье в блоге: