Неверный первый аргумент при использовании PyArg_ParseTuple - PullRequest
0 голосов
/ 06 ноября 2019

Я пишу методы для расширения типа AC:

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.

1 Ответ

1 голос
/ 06 ноября 2019

Код формата I ожидает, что будет передан указатель на unsigned int. Не npy_uint8 или npy_intp. unsigned int и только unsigned int. 8-битный uint, такой как vop, определенно является неправильным размером, поскольку попытка записи в него, как если бы он был нормальным unsigned int, вероятно, перезапишет некоторые другие данные. npy_intp может иметь или не иметь правильный размер, но так как он может быть неправильным, не используйте его.

Для первого аргумента вы хотите либо b, либо B, который являетсясимвол без знака (8 бит на почти каждой платформе). Прочитайте документацию для разницы. Второй аргумент, вероятно, захочет использовать K для unsigned long long, передать ему unsigned long long (который должен быть достаточно большим ...), а затем преобразовать его в npy_intp, проверяя наличие переполнения самостоятельно. В качестве альтернативы вы можете использовать O, а затем позвонить PyLong_AsVoidPtr, чтобы получить число до C.

В качестве отступления: npy_uint8 vop = 0xdeadbeef;, вероятно, должно сгенерировать предупреждение, так как номер выиграл 'вписывается в 8 бит.

...