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