Вызов функций 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
Для подробного руководства вы можете обратиться к моей статье в блоге: