使用 C 扩展 Python 时,如何在 C 中动态构建复杂结构?

When extending Python with C, How do one dynamically build a complex structure in C?

我想创建一个 C 函数,其中 returns 一个元组列表、一个字典列表或更好的一个 class 我在另一个 [=] 中定义的对象列表27=]模块。

关于 C API 的文档(«The Python/C API»)提到要构建一个复杂的对象,我需要调用 Py_BuildValue 它使用可变数量的参数或使用 va_list 参数的 Py_VaBuildValue

由于 C 无法使用可变数量的参数动态调用,因此我不能使用 Py_BuildValue 而必须使用 Py_VaBuildValue,但正在寻找如何构建 va_list 变量,我发现 There's no ability to fill a va_list explicitly and tells me to make it from a variable parameters function 的回复违背了目的...从所做的测试中,我得到的只是分段错误和核心转储。

那么,我应该如何使用这些功能?

您不应该使用这些函数来构建动态大小的数据结构。 FAQ 表示对任意大小的元组使用 PyTuple_Pack 而不是 Py_BuildValue ,但这也是错误的;我不知道为什么这么说。 PyTuple_Pack 与 Py_BuildValue.

具有相同的可变参数问题

要从 C 构建可变长度元组,请使用 PyTuple_New to construct an uninitialized tuple of the desired length, then loop over the indices and set the elements with PyTuple_SET_ITEM。是的,这会改变元组。 PyTuple_SET_ITEM 只有 可以安全地用于初始化尚未暴露给其他代码的新元组。另外,请注意 PyTuple_SET_ITEM 窃取了对新元素的引用。

例如,构建一个从 0 到 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_NewPyList_SET_ITEM 做同样的事情,或者您可以使用 PyList_New(0) 构建一个空列表并追加项目使用 PyList_Append,就像您在 Python 中使用 []append,如果您没有列表理解或序列乘法。