我在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 documentation说PyTuple_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;
}
应该可以解决问题,而事实并非如此。相反,我遇到了段错误。 我在这里想念什么?
答案 0 :(得分:4)
区别是:
Py_BuildValue("(ii)", a, b)
期望a
和b
是简单的C-int值。PyTuple_Pack(2, a, b)
期望a
和b
已经是PyObject
(而不是C整数)。将元组值初始化为指向 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.
因此,只需确保格式字符串中有括号,并且返回的值将是元组。