Python C API: PyEval_CallFunction?

5 投票
2 回答
2978 浏览
提问于 2025-04-16 11:23

我发现了一个在Python C API中叫做 PyEval_CallFunction 的函数,感觉这个函数挺有用的。它可以让你通过类似下面的方式来调用Python中的可调用对象:

PyEval_CallFunction(obj, "OOO", a, b, c);

不过,我找不到这个函数的官方文档。用谷歌搜索一下,能找到一些非官方的教程,讨论这个函数,但:

  1. 这个函数在官方Python文档中没有记录,所以我不知道它是否应该是公共API的一部分。

  2. 在网上搜索时,发现使用这个函数的规则不一致。有些教程说格式字符串需要在类型列表周围加上括号,比如 "(OiiO)",而其他时候我看到它没有括号。实际上在我的程序中尝试这个函数时,它似乎需要括号,否则就会出现错误。

我想用这个函数,因为它很方便。有没有人知道这个函数的情况,或者知道为什么没有文档?它是公共API的一部分吗?

2 个回答

5

之所以没有文档说明,是因为你应该使用 PyObject_CallFunction 这个函数。

PyEval_* 这一系列函数是用来进行解释器评估循环的底层内部调用。与之对应的、已经有文档的 PyObject_* 函数则包含了额外的检查,比如确保解释器的状态是正确的、验证参数是否有效,以及保护调用栈。

5

我也没找到很多相关的资料,不过你提到的那个教程里有这么一句:

字符串格式和后面的参数跟 Py_BuildValue 是一样的(XXX 所以我应该早就解释这个了!)。像这样的调用:

PyEval_CallFunction(obj, "iii", a, b, c);

其实是等同于:

PyEval_CallObject(obj, Py_BuildValue("iii", a, b, c));

我觉得 PyEval_CallFunction 可能不是公开的API,因为它的用途似乎比较有限。这两个之间其实没什么大区别。不过,我自己并没有深入参与Python扩展的开发,所以这只是我个人的看法。

PyEval_CallObject 本身只是一个宏,它是围绕 PyEval_CallObjectWithKeywords 这个函数的。

#define PyEval_CallObject(func,arg) \
        PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL)

关于“什么是公开API?”这里有马丁·冯·洛维斯的最近一条消息:

我想强调并支持乔治的解释:API并不是通过文档来定义的,而主要是通过头文件来定义的。所有声明为 PyAPI_FUNC 且不以 _Py 开头的函数都是公开API。以前有很多没有文档的API(在1.4之前,根本没有API文档,只有扩展模块的教程);现在,越来越多的API开始有文档了。

http://mail.python.org/pipermail/python-dev/2011-February/107973.html

撰写回答