Вызов Python из C | Комплект 1
В этой статье мы в основном сосредоточимся на безопасном выполнении вызываемого Python из C, возвращении результата обратно в C и написании кода C, который должен обращаться к функции Python в качестве обратного вызова.
В приведенном ниже коде основное внимание уделяется сложным частям, связанным с вызовом Python из C.
Code #1 : [Step 1 and 2] Own the GIL and Verify that function is a proper callable
#include <Python.h> /* Execute func(x, y) in the Python interpreter. The arguments and return result of the function must be Python floats */ double call_func(PyObject *func, double x, double y) { PyObject *args; PyObject *kwargs; PyObject *result = 0; double retval; // Make sure we own the GIL PyGILState_STATE state = PyGILState_Ensure(); // Verify that func is a proper callable if (!PyCallable_Check(func)) { fprintf (stderr, "call_func: expected a callable
" ); goto fail; } |
Код # 2: построение аргументов, функция вызова, проверка исключений Python
Создайте возвращаемое значение, восстановите предыдущее состояние GIL и вернитесь.
// Step3 args = Py_BuildValue( "(dd)" , x, y); kwargs = NULL; // Step 4 result = PyObject_Call(func, args, kwargs); Py_DECREF(args); Py_XDECREF(kwargs); // Step 5 if (PyErr_Occurred()) { PyErr_Print(); goto fail; } // Verify the result is a float object if (!PyFloat_Check(result)) { fprintf (stderr, "call_func: callable didn"t return a float
" ); goto fail; } // Step 6 retval = PyFloat_AsDouble(result); Py_DECREF(result); // Step 7 PyGILState_Release(state); return retval; fail: Py_XDECREF(result); PyGILState_Release(state); abort (); } |
Чтобы использовать эту функцию, необходимо передать ссылку на существующий вызываемый Python. Для этого есть много способов, например просто написать код на C для извлечения символа из существующего модуля или передать вызываемый объект в модуль расширения.
В приведенном ниже коде показан вызов функции из встроенного интерпретатора Python.
Code #3 : Loading a symbol from a module
#include <Python.h> /* Definition of call_func() same as above */ /* Load a symbol from a module */ PyObject *import_name( const char *modname, const char *symbol) { PyObject *u_name, *module; u_name = PyUnicode_FromString(modname); module = PyImport_Import(u_name); Py_DECREF(u_name); return PyObject_GetAttrString(module, symbol); } |
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.