Вызов Python из C | Set 2

| | | | | | | | | | | | | | | |

Для использования этой функции необходимо передать ссылку на существующую вызываемую функцию Python. Есть много способов сделать это, например — просто напишите код C, чтобы извлечь символ из существующего модуля или передать вызываемый объект плагину.

Код № 1: простой пример встраивания


int main ()

{

PyObject * pow_func;

double x;

Py_Initialize ();


// Получить ссылку на функцию math.pow

pow_func = import_name ( "math" , "pow" );


// Вызовите это, используя наш код call_func()

для (x = 0,0; x < 10,0; x + = 0,1)

{

printf ( "% 0.2f% 0.2f" , x, call_func (pow_func, x, 2.0));

}


Py_DECREF (pow_func);

Py_Finalize ();

return 0;

}

Чтобы построить этот последний пример, язык C должен для компиляции и компоновки с интерпретатором Python. Ниже приведен фрагмент кода, показывающий, как это сделать (это может потребовать некоторых усилий на вашем компьютере):

Код № 2:

< / p>

all::

cc -g embed.c -I /usr/local/include/python3 . 3m

- L /usr/local/lib/python3 . 3 / config-3 . 3m -lpython3.3m

Компиляция и запуск результирующего исполняемого файла дает следующий результат:

0,00 0,00 0,10 0,01 0,20 0,04 0,30 0,09 0,40 0,16 ... 

Ниже приведен еще один пример, представленный приведенным ниже кодом, который показывает функцию расширения, которая получает вызываемый объект и некоторые аргументы и отправляет их в call_func() в целях тестирования.

Код № 3:


/ * Функция расширения для тестирования обратного вызова C-Python * /


PyObject * py_call_func (PyObject * self, PyObject * args)
{

PyObject * функция;


double x, y, результат;

if (! PyArg_ParseTuple ( args, "Нечетный" , & func, & x, & y))

{

return NULL;

}

result = call_func (func, x, y);

return Py_BuildValue ( "d" , результат);

}

Код № 4: Тестирование функция расширения


import работает

def add (x, y ):

return x + y


work.call_func (add, 3 , 4 )

< /td>

Вывод:

7.0 

у нас был объект Python, представляющий вызываемый объект, который нужно вызвать. Это может быть функция, класс, метод, встроенный метод или что-то еще, что реализует __call__() . Чтобы проверить, является ли функция вызываемой, используйте PyCallable_Check() .

Код № 5: Проверка функции PyCallable_Check()

double call_func (PyObject * func, double x, double y)

{

...

// Проверяем правильность вызова func

if (! PyCallable_Check (func))

{

fprintf (stderr, "call_func: ожидается вызываемый объект" );

перейти fail;

}

...

Просто используйте PyObject_Call() для вызова функции, предоставив ей вызываемый объект, кортеж аргументов и необязательный словарь аргументов ключевого слова.

Py_BuildValue() можно использовать для создания кортежа или словаря аргументов.

Код № 6:

double call_func (PyObject * func, double x, double y)

{

PyObject * args;

PyObject * kwargs;


/ * Аргументы сборки * /

args = Py_BuildValue ( "(dd)" , x, y);

kwargs = NULL;

/ * Вызов функции * /

result = PyObject_Call (func, аргументы, кварги);

Py_DECREF (args);

Py_XDECREF (kwargs);



/ * Проверка исключений Python (если есть) * /

если (PyErr_Occurred ())

< класс кода ="plain "> {/code>

PyErr_Print ();

перейти fail;

}


сбой:

PyGILState_Release (состояние);

прервать ();


}