【问题标题】:When extending Python with C, How do one dynamically build a complex structure in C?使用 C 扩展 Python 时,如何在 C 中动态构建复杂结构?
【发布时间】:2019-05-04 21:41:28
【问题描述】:

我想做一个 C 函数,它返回一个元组列表、一个字典列表,甚至更好,一个我在另一个 python 模块中定义的类的对象列表。

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

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

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

【问题讨论】:

    标签: python c python-3.x variadic-functions


    【解决方案1】:

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

    要从 C 中构建可变长度元组,请使用 PyTuple_New 构建所需长度的未初始化元组,然后遍历索引并使用 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

    【讨论】:

    • 谢谢,它可以工作(除了我的代码中的错误 ;-) )。你知道我应该如何让我的 C 扩展从 python 模块中定义的类返回一个对象吗?
    • @Camion:与您在 Python 中执行此操作的方式相同。检索类对象并执行function call
    猜你喜欢
    • 1970-01-01
    • 2018-03-12
    • 2016-11-04
    • 2015-08-05
    • 2014-04-08
    • 2020-11-11
    • 2021-06-16
    • 2010-09-20
    • 2019-05-16
    相关资源
    最近更新 更多