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
|
|
@ -11,6 +11,24 @@ Version 3.0.11 (in progress)
|
|||
we checked an uninitialised value instead. Fixes #627. Based on
|
||||
patch from Sergey Seroshtan.
|
||||
|
||||
2016-09-22: wsfulton
|
||||
[Python] More flexible python builtin slots for overloaded C++ function.
|
||||
|
||||
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 */
|
||||
|
||||
Previously only one name was defined: _wrap_SimpleArray___getitem___closure.
|
||||
Hence the overloaded __getitem__ method can be used to support both mp_subscript and sq_item slots.
|
||||
|
||||
2016-09-17: wsfulton
|
||||
[Python] Fix iterators for containers of NULL pointers (or Python None) when using
|
||||
-builtin. Previously iteration would stop at the first element that was NULL.
|
||||
|
|
|
|||
|
|
@ -79,3 +79,16 @@ if is_python_builtin():
|
|||
if MyClass.less_than_counts != 6:
|
||||
raise RuntimeError("python:compare feature not working")
|
||||
|
||||
sa = SimpleArray(5)
|
||||
elements = [x for x in sa]
|
||||
if elements != [0, 10, 20, 30, 40]:
|
||||
raise RuntimeError("Iteration not working")
|
||||
if len(sa) != 5:
|
||||
raise RuntimeError("len not working")
|
||||
for i in range(5):
|
||||
if sa[i] != i*10:
|
||||
raise RuntimeError("indexing not working")
|
||||
subslice = sa[1:3]
|
||||
elements = [x for x in subslice]
|
||||
if elements != [10, 20]:
|
||||
raise RuntimeError("slice not working")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
%}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#define SWIGPY_UNARYFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_unaryfunc_closure(PyObject *a) { \
|
||||
return wrapper(a, NULL); \
|
||||
}
|
||||
|
||||
#define SWIGPY_DESTRUCTOR_CLOSURE(wrapper) \
|
||||
SWIGINTERN void \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_destructor_closure(PyObject *a) { \
|
||||
SwigPyObject *sobj; \
|
||||
sobj = (SwigPyObject *)a; \
|
||||
Py_XDECREF(sobj->dict); \
|
||||
|
|
@ -32,7 +32,7 @@ wrapper##_closure(PyObject *a) { \
|
|||
|
||||
#define SWIGPY_INQUIRY_CLOSURE(wrapper) \
|
||||
SWIGINTERN int \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_inquiry_closure(PyObject *a) { \
|
||||
PyObject *pyresult; \
|
||||
int result; \
|
||||
pyresult = wrapper(a, NULL); \
|
||||
|
|
@ -41,9 +41,15 @@ wrapper##_closure(PyObject *a) { \
|
|||
return result; \
|
||||
}
|
||||
|
||||
#define SWIGPY_GETITERFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_getiterfunc_closure(PyObject *a) { \
|
||||
return wrapper(a, NULL); \
|
||||
}
|
||||
|
||||
#define SWIGPY_BINARYFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a, PyObject *b) { \
|
||||
wrapper##_binaryfunc_closure(PyObject *a, PyObject *b) { \
|
||||
PyObject *tuple, *result; \
|
||||
tuple = PyTuple_New(1); \
|
||||
assert(tuple); \
|
||||
|
|
@ -58,7 +64,7 @@ typedef ternaryfunc ternarycallfunc;
|
|||
|
||||
#define SWIGPY_TERNARYFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
||||
wrapper##_ternaryfunc_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
||||
PyObject *tuple, *result; \
|
||||
tuple = PyTuple_New(2); \
|
||||
assert(tuple); \
|
||||
|
|
@ -73,13 +79,13 @@ wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
|||
|
||||
#define SWIGPY_TERNARYCALLFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *callable_object, PyObject *args, PyObject *) { \
|
||||
wrapper##_ternarycallfunc_closure(PyObject *callable_object, PyObject *args, PyObject *) { \
|
||||
return wrapper(callable_object, args); \
|
||||
}
|
||||
|
||||
#define SWIGPY_LENFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN Py_ssize_t \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_lenfunc_closure(PyObject *a) { \
|
||||
PyObject *resultobj; \
|
||||
Py_ssize_t result; \
|
||||
resultobj = wrapper(a, NULL); \
|
||||
|
|
@ -90,7 +96,7 @@ wrapper##_closure(PyObject *a) { \
|
|||
|
||||
#define SWIGPY_SSIZESSIZEARGFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \
|
||||
wrapper##_ssizessizeargfunc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \
|
||||
PyObject *tuple, *result; \
|
||||
tuple = PyTuple_New(2); \
|
||||
assert(tuple); \
|
||||
|
|
@ -103,7 +109,7 @@ wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \
|
|||
|
||||
#define SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE(wrapper) \
|
||||
SWIGINTERN int \
|
||||
wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \
|
||||
wrapper##_ssizessizeobjargproc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \
|
||||
PyObject *tuple, *resultobj; \
|
||||
int result; \
|
||||
tuple = PyTuple_New(d ? 3 : 2); \
|
||||
|
|
@ -123,7 +129,7 @@ wrapper##_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \
|
|||
|
||||
#define SWIGPY_SSIZEARGFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a, Py_ssize_t b) { \
|
||||
wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \
|
||||
PyObject *tuple, *result; \
|
||||
tuple = PyTuple_New(1); \
|
||||
assert(tuple); \
|
||||
|
|
@ -135,7 +141,7 @@ wrapper##_closure(PyObject *a, Py_ssize_t b) { \
|
|||
|
||||
#define SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a, Py_ssize_t b) { \
|
||||
wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \
|
||||
PyObject *arg, *result; \
|
||||
arg = _PyLong_FromSsize_t(b); \
|
||||
result = wrapper(a, arg); \
|
||||
|
|
@ -145,7 +151,7 @@ wrapper##_closure(PyObject *a, Py_ssize_t b) { \
|
|||
|
||||
#define SWIGPY_SSIZEOBJARGPROC_CLOSURE(wrapper) \
|
||||
SWIGINTERN int \
|
||||
wrapper##_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \
|
||||
wrapper##_ssizeobjargproc_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \
|
||||
PyObject *tuple, *resultobj; \
|
||||
int result; \
|
||||
tuple = PyTuple_New(2); \
|
||||
|
|
@ -162,7 +168,7 @@ wrapper##_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \
|
|||
|
||||
#define SWIGPY_OBJOBJARGPROC_CLOSURE(wrapper) \
|
||||
SWIGINTERN int \
|
||||
wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
||||
wrapper##_objobjargproc_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
||||
PyObject *tuple, *resultobj; \
|
||||
int result; \
|
||||
tuple = PyTuple_New(c ? 2 : 1); \
|
||||
|
|
@ -182,13 +188,13 @@ wrapper##_closure(PyObject *a, PyObject *b, PyObject *c) { \
|
|||
|
||||
#define SWIGPY_REPRFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_reprfunc_closure(PyObject *a) { \
|
||||
return wrapper(a, NULL); \
|
||||
}
|
||||
|
||||
#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN Py_hash_t \
|
||||
wrapper##_closure(PyObject *a) { \
|
||||
wrapper##_hashfunc_closure(PyObject *a) { \
|
||||
PyObject *pyresult; \
|
||||
Py_hash_t result; \
|
||||
pyresult = wrapper(a, NULL); \
|
||||
|
|
@ -199,6 +205,12 @@ wrapper##_closure(PyObject *a) { \
|
|||
return result; \
|
||||
}
|
||||
|
||||
#define SWIGPY_ITERNEXTFUNC_CLOSURE(wrapper) \
|
||||
SWIGINTERN PyObject * \
|
||||
wrapper##_iternextfunc_closure(PyObject *a) { \
|
||||
return wrapper(a, NULL); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,11 +47,13 @@ static Hash *f_shadow_imports = 0;
|
|||
static String *f_shadow_builtin_imports = 0;
|
||||
static String *f_shadow_stubs = 0;
|
||||
static Hash *builtin_getset = 0;
|
||||
static Hash *builtin_closures = 0;
|
||||
static Hash *class_members = 0;
|
||||
static File *f_builtins = 0;
|
||||
static String *builtin_tp_init = 0;
|
||||
static String *builtin_methods = 0;
|
||||
static String *builtin_default_unref = 0;
|
||||
static String *builtin_closures_code = 0;
|
||||
|
||||
static String *methods;
|
||||
static String *class_name;
|
||||
|
|
@ -188,7 +190,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
|
|||
"unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
|
||||
"inquiry", "SWIGPY_INQUIRY_CLOSURE",
|
||||
"getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
|
||||
"binaryfunc", "SWIGPY_BINARYFUNC_CLOSURE",
|
||||
"ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
|
||||
"ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
|
||||
|
|
@ -200,7 +202,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
|
|||
"objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
|
||||
"reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
|
||||
"hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
|
||||
"iternextfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -208,7 +210,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
|
|||
"unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
|
||||
"inquiry", "SWIGPY_INQUIRY_CLOSURE",
|
||||
"getiterfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
|
||||
"ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
|
||||
"ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
|
||||
"lenfunc", "SWIGPY_LENFUNC_CLOSURE",
|
||||
|
|
@ -219,7 +221,7 @@ static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
|
|||
"objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
|
||||
"reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
|
||||
"hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
|
||||
"iternextfunc", "SWIGPY_UNARYFUNC_CLOSURE",
|
||||
"iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -626,6 +628,8 @@ public:
|
|||
f_directors_h = NewString("");
|
||||
f_directors = NewString("");
|
||||
builtin_getset = NewHash();
|
||||
builtin_closures = NewHash();
|
||||
builtin_closures_code = NewString("");
|
||||
class_members = NewHash();
|
||||
builtin_methods = NewString("");
|
||||
builtin_default_unref = NewString("delete $self;");
|
||||
|
|
@ -3328,11 +3332,12 @@ public:
|
|||
String *func_type = Getattr(n, "feature:python:slot:functype");
|
||||
String *closure_decl = getClosure(func_type, wrapper_name, overname ? 0 : funpack);
|
||||
String *feature_name = NewStringf("feature:python:%s", slot);
|
||||
String *closure_name = Copy(wrapper_name);
|
||||
String *closure_name = 0;
|
||||
if (closure_decl) {
|
||||
Append(closure_name, "_closure");
|
||||
if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling"))
|
||||
Printf(f_wrappers, "%s /* defines %s */\n\n", closure_decl, closure_name);
|
||||
closure_name = NewStringf("%s_%s_closure", wrapper_name, func_type);
|
||||
if (!GetFlag(builtin_closures, closure_name))
|
||||
Printf(builtin_closures_code, "%s /* defines %s */\n\n", closure_decl, closure_name);
|
||||
SetFlag(builtin_closures, closure_name);
|
||||
Delete(closure_decl);
|
||||
}
|
||||
if (func_type) {
|
||||
|
|
@ -4511,7 +4516,12 @@ public:
|
|||
SwigType *realct = Copy(real_classname);
|
||||
SwigType_add_pointer(realct);
|
||||
SwigType_remember(realct);
|
||||
if (!builtin) {
|
||||
if (builtin) {
|
||||
Printv(f_wrappers, builtin_closures_code, NIL);
|
||||
Delete(builtin_closures_code);
|
||||
builtin_closures_code = NewString("");
|
||||
Clear(builtin_closures);
|
||||
} else {
|
||||
Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
|
||||
Printv(f_wrappers, " PyObject *obj;\n", NIL);
|
||||
if (modernargs) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue