从 C 调用Python |设置 2
先决条件:从 C 调用Python |设置 1
需要传入对现有Python可调用对象的引用才能使用此函数。要做到这一点,有很多方法,比如简单地编写 C 代码以从现有模块中提取符号或将可调用对象传递给扩展模块。
代码 #1:简单的嵌入示例
int main()
{
PyObject * pow_func;
double x;
Py_Initialize();
// Get a reference to the math.pow function
pow_func = import_name("math", "pow");
// Call it using our call_func() code
for (x = 0.0; x < 10.0; x += 0.1)
{
printf("% 0.2f % 0.2f\n", x, call_func(pow_func, x, 2.0));
}
Py_DECREF(pow_func);
Py_Finalize();
return 0;
}
要构建最后一个示例,需要编译 C 并链接到Python解释器。下面的片段显示了如何做到这一点(这可能需要在您的机器上进行一些摆弄):
代码#2:
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:
/* Extension function for testing the C-Python callback */
PyObject * py_call_func(PyObject * self, PyObject * args)
{
PyObject * func;
double x, y, result;
if (! PyArg_ParseTuple(args, "Odd", &func, &x, &y))
{
return NULL;
}
result = call_func(func, x, y);
return Py_BuildValue("d", result);
}
代码#4:测试扩展函数
import work
def add(x, y):
return x + y
work.call_func(add, 3, 4)
输出 :
7.0
至关重要的是,首先我们需要一个Python对象来表示要调用的可调用对象。这可以是函数、类、方法、内置方法或任何实现__call__()
操作的东西。要验证它是否是可调用函数,请使用PyCallable_Check()
。
代码 #5:检查PyCallable_Check()
函数
double call_func(PyObject *func, double x, double y)
{
...
// Verify that func is a proper callable
if (!PyCallable_Check(func))
{
fprintf(stderr, "call_func: expected a callable\n");
goto fail;
}
...
只需使用PyObject_Call()
调用一个函数,为它提供可调用对象、一个参数元组和一个可选的关键字参数字典。
Py_BuildValue()
可用于构建参数元组或字典。
代码#6:
double call_func(PyObject *func, double x, double y)
{
PyObject *args;
PyObject *kwargs;
/* Build arguments */
args = Py_BuildValue("(dd)", x, y);
kwargs = NULL;
/* Call the function */
result = PyObject_Call(func, args, kwargs);
Py_DECREF(args);
Py_XDECREF(kwargs);
/* Check for Python exceptions (if any) */
if (PyErr_Occurred())
{
PyErr_Print();
goto fail;
}
fail:
PyGILState_Release(state);
abort();
}