PyTuple_Pack段错误 [英] `PyTuple_Pack` segfault

查看:84
本文介绍了PyTuple_Pack段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Python扩展模块中有一个函数 foo ,该函数应该将int元组返回给Python.使用 Py_BuildValue :

I have a function foo in a Python Extension Module that should return a tuple of ints to Python. This can be easily done using 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;
}

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

Instead of Py_BuildValue, I want to use PyTuple_Pack, which ensures that the return value is indeed a tuple.

Python C API文档说, PyTuple_Pack(3,a,b,a + b)等效于 Py_BuildValue((iii)",a,b,a + b).这两个函数均返回类型为 PyPbject * 的新引用.

The Python C API documentation says that PyTuple_Pack(3, a, b, a+b) is equivalent to Py_BuildValue("(iii)", a, b, a+b). Both functions return a new reference of type PyPbject*.

因此,鉴于上面的代码,

Hence, given the code above,

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

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

    return out;
}

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

should do the trick, which is does not. Instead I get a segfault. What am I missing here?

推荐答案

区别是:

  • Py_BuildValue((ii)",a,b)期望 a b 是简单的C-int值.
  • PyTuple_Pack(2,a,b)期望 a b 已经是 PyObject s(和不是C-ints.)
  • Py_BuildValue("(ii)", a, b) expects a and b to be simple C-int values.
  • PyTuple_Pack(2, a, b) expects a and b to be already PyObjects (and not C-ints).

文档说:

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

The tuple values are initialized to the subsequent n C arguments pointing to Python objects. PyTuple_Pack(2, a, b) is equivalent to Py_BuildValue("(OO)", a, b).

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

In order to use PyTuple_Pack you need to convert the int-values to Python-Integers first.

使用 Py_BuildValue()更简单.如果您在 Py_BuildValue ,结果将是一个元组:

It is simpler to use Py_BuildValue(). If you parenthesize your format string in Py_BuildValue, the result will be a tuple:

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

Py_BuildValue() does not always build a tuple. It builds a tuple only if its format string contains two or more format units. If the format string is empty, it returns None; if it contains exactly one format unit, it returns whatever object is described by that format unit. To force it to return a tuple of size 0 or one, parenthesize the format string.

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

That means: there is nothing to worry about if you construct a tuple from at least two elements:

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

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

It is different if there is only one element:

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.

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

So just make sure there are parenthesizes in the format string and the returned value will be a tuple.

这篇关于PyTuple_Pack段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆