使用 C 扩展 Python 时,如何在 C 中动态构建复杂结构? [英] When extending Python with C, How do one dynamically build a complex structure in C?
问题描述
我想创建一个 C 函数,它返回一个元组列表、一个字典列表,或者更好的是,一个我在另一个 python 模块中定义的类的对象列表.
I'd like to make a C function which returns a list of tuples, a list of dicts or even better, a list of objects of a class I defined in another python module.
关于 C API(«The Python/C API»)的文档提到要构建一个复杂的对象,我需要调用 Py_BuildValue
它使用可变数量的参数或 Py_VaBuildValue
使用 va_list
参数.
The documentation on the C API («The Python/C API») mentions that to build a complex object, I need to call to Py_BuildValue
which uses a Variable number of parameters or Py_VaBuildValue
which uses a va_list
argument.
由于 C 不能用可变数量的参数动态调用,所以我不能使用 Py_BuildValue
并且必须使用 Py_VaBuildValue
,但正在寻找如何构建一个 va_list
变量,我找到了 没有能力显式填充 va_list 和 告诉我用可变参数函数制作它,这违背了目的......从所做的测试中,我得到的只是分段错误和核心转储.
Since C cannot dynamically make a call with a variable number of arguments, I cannot use Py_BuildValue
and must use Py_VaBuildValue
, but looking for how to build a va_list
variable, I find replies which the There's no ability to fill a va_list explicitly and tells me to make it from a variable parameters function, which defeats the purpose... and from the tests a made, all I get is segmentation faults and core dumps.
那么,我应该如何使用这些功能?
So, how am I Supposed to use those functions ?
推荐答案
您不应该使用这些函数来构建动态大小的数据结构.FAQ 说对任意大小的元组使用 PyTuple_Pack 而不是 Py_BuildValue,但这也是错误的;我不知道为什么这么说.PyTuple_Pack 具有与 Py_BuildValue 相同的可变参数问题.
You're not supposed to use those functions to build dynamically-sized data structures. The FAQ says to use PyTuple_Pack instead of Py_BuildValue for an arbitrary-sized tuple, but that's wrong too; I don't know why it says that. PyTuple_Pack has the same varargs issues as Py_BuildValue.
要从 C 构建可变长度元组,请使用 PyTuple_New
构建未初始化的元组所需的长度,然后遍历索引并使用 设置元素PyTuple_SET_ITEM
.是的,这会改变元组.PyTuple_SET_ITEM
仅可以安全地用于初始化尚未暴露给其他代码的新元组.另外,请注意 PyTuple_SET_ITEM
会窃取对新元素的引用.
To build a variable-length tuple from C, use PyTuple_New
to construct an uninitialized tuple of the desired length, then loop over the indices and set the elements with PyTuple_SET_ITEM
. Yes, this mutates the tuple. PyTuple_SET_ITEM
is only safe to use to initialize fresh tuples that have not yet been exposed to other code. Also, be aware that PyTuple_SET_ITEM
steals a reference to the new element.
例如,构建一个从 0 到 n-1 的整数元组:
For example, to build a tuple of integers from 0 to n-1:
PyObject *tup = PyTuple_New(n);
for (int i = 0; i < n; i++) {
// Note that PyTuple_SET_ITEM steals the reference we get from PyLong_FromLong.
PyTuple_SET_ITEM(tup, i, PyLong_FromLong(i));
}
要从 C 构建可变长度列表,您可以使用 PyList_New
和 PyList_SET_ITEM
做同样的事情,或者您可以使用 PyList_New 构建一个空列表(0)
并使用 PyList_Append
附加项目,就像你在 Python 中使用 []
和 append
一样,如果你没有有列表推导式或序列乘法.
To build a variable-length list from C, you can do the same thing with PyList_New
and PyList_SET_ITEM
, or you can construct an empty list with PyList_New(0)
and append items with PyList_Append
, much like you would use []
and append
in Python if you didn't have list comprehensions or sequence multiplication.
这篇关于使用 C 扩展 Python 时,如何在 C 中动态构建复杂结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!