使用 PyArg_ParseTuple 时第一个参数错误

Wrong first argument when using PyArg_ParseTuple

我为 c 扩展类型编写方法:

static PyObject *
RawGraphState_apply_C_L(RawGraphState * self
                        , PyObject * args)
{
    npy_uint8 vop = 0xdeadbeef;
    npy_intp i;// = 0xdeadbeef;

    if(!PyArg_ParseTuple(args, "II", &i, &vop))
    {
        return NULL;
    }

    printf("i = %ld\n", i);

    if(vop >= 24)
    {
        PyErr_SetString(PyExc_ValueError, "vop index must be in [0, 23]");
        return NULL;
    }

    if(i >= self->length)
    {
        PyErr_SetString(PyExc_ValueError, "qbit index out of range");
        return NULL;
    }

    printf("mapping vop[%ld] %d,%d -> %d\n", i, vop, self->vops[i], vop_lookup_table[vop][self->vops[i]]);
    self->vops[i] = vop_lookup_table[vop][self->vops[i]];

    Py_RETURN_NONE;

}

然而,这并没有正确读取第一个参数。它默认为 0 或一个巨大的数字(取决于我在 pytest 或使用 ipython 中调用方法):

In [1]: from pyqcs.graph.backend.raw_state import RawGraphState                                                                        
^[[A
In [2]: g = RawGraphState(2)                                                                                                           

In [3]: g.apply_C_L(1, 0)                                                                                                              
i = 140200617443328
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-57081093fbb3> in <module>
----> 1 g.apply_C_L(1, 0)

ValueError: qbit index out of range

我做错了什么?

--

您可以在这里找到代码:

https://github.com/daknuett/PyQCS/blob/graph_simulation/src/pyqcs/graph/backend/raw_state.c

从第 300 行开始。

格式代码 I 需要传递一个指向 unsigned int 的指针。不是 npy_uint8npy_intp。一个 unsigned int,而且只有一个 unsigned int。像 vop 这样的 8 位 uint 绝对是错误的大小,因为尝试将其写入就好像它是正常的 unsigned int 一样可能会覆盖一些其他数据。 npy_intp 大小可能正确,也可能不正确,但由于它可能是错误的,所以不要使用它。

对于第一个参数,您需要 bB,这是一个无符号字符(几乎每个平台上都是 8 位)。阅读文档以了解差异。对于第二个参数,可能想将 K 用于 unsigned long long,将其传递给 unsigned long long(应该足够大...),然后将其转换为 npy_intp 自己检查溢出。或者,您可以使用 O 然后调用 PyLong_AsVoidPtr 将号码发送给 C.

顺便说一句:npy_uint8 vop = 0xdeadbeef; 可能会生成警告,因为该数字不适合 8 位。