2

I have an 2d matrix class in c that I am using in python. I want to be able to call the matrix class by passing a tuple of slice objects, e.g., A[1:2,1:2]. So far what I have is the following. The relevant C code for the __getitem__ method looks like

   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) ; 
    } 

This code checks whether slice2 is indeed a slice object using the PySlice_Check method. If I comment out PySlice_GetIndicesEx(slice1,length,&start,&stop,&step), I get a 1 as expected. However, if I leave this line in, I get an error:

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

which means I cannot pass slice1 or slice2 into PySlice_GetIndicesEx since it needs a PySliceObject object.

How do I unravel the slice objects properly so I can pass it into PySlice_GetIndicesEx. This function takes in PySliceObject and not a PyObject, which is what slice1 and slice2 is, even though PySlice_Check(slice1) and PySlice_Check(slice2) both return a 1.

Bluegreen17
  • 983
  • 1
  • 11
  • 25

2 Answers2

3

Here is the solution thanks to A. Taggart.:

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;

The key here is to pass (PySliceObject*)slice1 which passes the slice object as a PySliceObject.

Community
  • 1
  • 1
Bluegreen17
  • 983
  • 1
  • 11
  • 25
0

__getitem__ takes a single argument, which in your case is a tuple of two slice-objects. That means that in C, slices points to a single tuple containing two slice-objects.

   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
Alan
  • 1,889
  • 2
  • 18
  • 30
Daniel
  • 42,087
  • 4
  • 55
  • 81
  • Thanks for the help. However, when I try using `PySlice_GetIndicesEx(slice1,length,&start,&stop,&step)` I get the same error: `error: cannot convert 'PyObject* {aka _object*}' to 'PySliceObject*' for argument '1' to 'int PySlice_GetIndices`. Is there another way to get the start and stop values of the slice1 object? – Bluegreen17 Apr 22 '14 at 18:08