PyTuple_Pack段错误

时间:2018-09-05 07:45:46

标签: python python-3.x cpython python-extensions

我在Python扩展模块中有一个函数foo,该函数应将一个整数元组返回给Python。使用Py_BuildValue可以轻松完成:

static PyObject* 
foo(PyObject* self, PyObject* args)
{
    int a = 0;
    int b = 0;

    /* calculations and stuff */

    PyObject* out = Py_BuildValue("(iii)", a, b, a+b);
    Py_INCREF(out);

    return out;
}

我要使用Py_BuildValue而不是PyTuple_Pack,这可以确保返回值确实是一个元组。

Python C API documentationPyTuple_Pack(3, a, b, a+b)等效于Py_BuildValue("(iii)", a, b, a+b)。这两个函数都返回类型为PyPbject*的新引用。

因此,鉴于上面的代码,

static PyObject* 
foo(PyObject* self, PyObject* args)
{
    /* ... */

    PyObject* out = PyTuple_Pack(3, a, b, a+b);
    Py_INCREF(out);

    return out;
}

应该可以解决问题,而事实并非如此。相反,我遇到了段错误。 我在这里想念什么?

1 个答案:

答案 0 :(得分:4)

区别是:

  • Py_BuildValue("(ii)", a, b)期望ab是简单的C-int值。
  • PyTuple_Pack(2, a, b)期望ab已经是PyObject(而不是C整数)。

documentation说:

  

将元组值初始化为指向 Python对象的后续n个C参数。 PyTuple_Pack(2, a, b)等同于Py_BuildValue("(OO)", a, b)

要使用PyTuple_Pack,您需要先将int值转换为Python-Integers。

使用Py_BuildValue()更简单。如果在Py_BuildValue中加上格式字符串,则结果将是一个元组:

  

Py_BuildValue()并不总是建立一个元组。仅当其格式字符串包含两个或多个格式单位时,才会构建元组。如果格式字符串为空,则返回None;否则,返回0。如果它仅包含一个格式单元,则返回该格式单元描述的任何对象。 要强制其返回大小为0或1的元组,请用括号括住格式字符串

这意味着:如果您至少由两个元素构成一个元组,则无需担心:

Py_BuildValue("ii", a, b)   # returns a tuple
Py_BuildValue("(ii)", a, b) # returns a tuple

只有一个元素会有所不同:

Py_BuildValue("i", a)    # returns an integer
# parenthesized:
Py_BuildValue("(i)", a)  # returns a tuple with an integer

或完全没有元素:

Py_BuildValue("")    # returns None
# parenthesized:
Py_BuildValue("()")  # returns an empty tuple.

因此,只需确保格式字符串中有括号,并且返回的值将是元组。