More flexible python builtin slots
The closure names used for builtin slots are mangled with their functype so
that overloaded C++ method names can be used for multiple slots.
For example:
%feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__;
%feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n);
will generate closures:
SWIGPY_SSIZEARGFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___ssizeargfunc_closure */
SWIGPY_BINARYFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___binaryfunc_closure */
This commit is contained in:
parent
5b8e8fa107
commit
848628ae91
5 changed files with 140 additions and 24 deletions
|
|
@ -136,3 +136,66 @@ void Dealloc2Destroyer(PyObject *v) {
|
|||
};
|
||||
int MyClass::less_than_counts = 0;
|
||||
%}
|
||||
|
||||
// Test 6 add in container __getitem__ to support basic sequence protocol
|
||||
// Tests overloaded functions being used for more than one slot (mp_subscript and sq_item)
|
||||
%include <exception.i>
|
||||
%include <std_except.i>
|
||||
%apply int {Py_ssize_t}
|
||||
%typemap(in) PySliceObject * {
|
||||
if (!PySlice_Check($input))
|
||||
SWIG_exception(SWIG_TypeError, "in method '$symname', argument $argnum of type '$type'");
|
||||
$1 = (PySliceObject *)$input;
|
||||
}
|
||||
%typemap(typecheck,precedence=300) PySliceObject* {
|
||||
$1 = PySlice_Check($input);
|
||||
}
|
||||
|
||||
%feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__(PySliceObject *slice);
|
||||
%feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n);
|
||||
%feature("python:slot", "sq_length", functype="lenfunc") SimpleArray::__len__;
|
||||
%inline %{
|
||||
class SimpleArray {
|
||||
size_t size;
|
||||
int numbers[5];
|
||||
public:
|
||||
SimpleArray(size_t size) : size(size) {
|
||||
for (size_t x = 0; x<size; ++x)
|
||||
numbers[x] = x*10;
|
||||
}
|
||||
|
||||
Py_ssize_t __len__() {
|
||||
return size;
|
||||
}
|
||||
|
||||
int __getitem__(Py_ssize_t n) throw (std::out_of_range) {
|
||||
if (n >= (int)size)
|
||||
throw std::out_of_range("Index too large");
|
||||
return numbers[n];
|
||||
}
|
||||
|
||||
SimpleArray __getitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) {
|
||||
if (!PySlice_Check(slice))
|
||||
throw std::invalid_argument("Slice object expected");
|
||||
Py_ssize_t i, j, step;
|
||||
#if PY_VERSION_HEX >= 0x03020000
|
||||
PySlice_GetIndices((PyObject *)slice, size, &i, &j, &step);
|
||||
#else
|
||||
PySlice_GetIndices((PySliceObject *)slice, size, &i, &j, &step);
|
||||
#endif
|
||||
if (step != 1)
|
||||
throw std::invalid_argument("Only a step size of 1 is implemented");
|
||||
|
||||
{
|
||||
Py_ssize_t ii = i<0 ? 0 : i>=size ? size-1 : i;
|
||||
Py_ssize_t jj = j<0 ? 0 : j>=size ? size-1 : j;
|
||||
if (ii > jj)
|
||||
throw std::invalid_argument("getitem i should not be larger than j");
|
||||
SimpleArray n(jj-ii);
|
||||
for (size_t x = 0; x<size; ++x)
|
||||
n.numbers[x] = numbers[x+ii];
|
||||
return n;
|
||||
}
|
||||
}
|
||||
};
|
||||
%}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue