Как передать кортеж объектов среза в C через API python-C

У меня есть класс 2d-матрицы в c, который я использую в python. Я хочу иметь возможность вызывать матричный класс, передавая кортеж объектов среза, например, A[1:2,1:2]. Пока что имею следующее. Соответствующий код C для метода __getitem__ выглядит так:

   int __getitem__(PyObject *slices){       // get tuple of slice objects
       PyObject* slice1;                    // declare first slice object
       PyObject* slice2;                    // declare second slice object       
       slice1 = PyTuple_GetItem(slices, 0); // get first slice from tuple
       slice2 = PyTuple_GetItem(slices, 1); // get second slice from tuple

        // get start and stop of first slice (currently the following three lines do not work)  
        Py_ssize_t start, stop, step, length; 
        PySlice_GetIndicesEx(slice1,length,&start,&stop,&step); 

     return PySlice_Check(slice2) ; 
    } 

Этот код проверяет, действительно ли slice2 является объектом слайса, используя метод PySlice_Check. Если я закомментирую PySlice_GetIndicesEx(slice1,length,&start,&stop,&step), я получу 1, как и ожидалось. Однако, если я оставлю эту строку, я получаю сообщение об ошибке:

cannot convert 'PyObject* {aka _object*}' to 'PySliceObject*' for argument '1' to 'int PySlice_GetIndicesEx(...

что означает, что я не могу передать slice1 или slice2 в PySlice_GetIndicesEx, так как ему нужен объект PySliceObject.

Как мне правильно распутать объекты среза, чтобы я мог передать их в PySlice_GetIndicesEx. Эта функция принимает PySliceObject, а не PyObject, что и есть slice1 и slice2, даже если PySlice_Check(slice1) и PySlice_Check(slice2) возвращают 1.


person Bluegreen17    schedule 22.04.2014    source источник


Ответы (2)


Вот решение благодаря А. Таггарт.:

int __getitem__(PyObject *slices){
    PyObject* slice1;
    PyObject* slice2;    
    slice1 = PyTuple_GetItem(slices, 0);
    slice2 = PyTuple_GetItem(slices, 1);

    Py_ssize_t len = 0, start1 = 0, stop1 = 0, step1 = 0, slicelength1 = 0;
    Py_ssize_t start2 = 0, stop2 = 0, step2 = 0, slicelength2 = 0;
    len = (*self).size() // or however you get the length of the slice
    PySlice_GetIndicesEx((PySliceObject*)slice1,len,&start1,&stop1,&step1,&slicelength1);
    PySlice_GetIndicesEx((PySliceObject*)slice2,len,&start2,&stop2,&step2,&slicelength2);

return 0;

Ключевым моментом здесь является передача (PySliceObject*)slice1, которая передает объект среза как PySliceObject.

person Bluegreen17    schedule 22.04.2014

__getitem__ принимает один аргумент, который в вашем случае представляет собой кортеж из двух объектов-срезов. Это означает, что в C slices указывает на один кортеж, содержащий два объекта-среза.

   PyObject* indices;
   PyObject* slice1;
   PyObject* slice2;
   indices = PyTuple_GetItem(slices, 0); // get tuple
   slice1 = PyTuple_GetItem(indices, 0); // get first slice from tuple
   slice2 = PyTuple_GetItem(indices, 1); // get second slice from tuple
person Daniel    schedule 22.04.2014
comment
Спасибо за помощь. Однако, когда я пытаюсь использовать PySlice_GetIndicesEx(slice1,length,&start,&stop,&step), я получаю ту же ошибку: error: cannot convert 'PyObject* {aka _object*}' to 'PySliceObject*' for argument '1' to 'int PySlice_GetIndices. Есть ли другой способ получить начальное и конечное значения объекта slice1? - person Bluegreen17; 22.04.2014