From 174523aa80935add2688bcb055a0a195c7ffbe4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tomulik?= Date: Wed, 23 Mar 2016 15:33:42 +0100 Subject: [PATCH] fix handling of function pointers by %constant directive --- Examples/test-suite/constant_directive.i | 43 ++++++++++++------- .../java/constant_directive_runme.java | 4 ++ .../python/constant_directive_runme.py | 8 ++++ Lib/python/pytypemaps.swg | 4 +- Lib/typemaps/swigtype.swg | 1 + Source/Modules/python.cxx | 32 +++++++++++--- 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/Examples/test-suite/constant_directive.i b/Examples/test-suite/constant_directive.i index 8204720d6..fc6b6cd92 100644 --- a/Examples/test-suite/constant_directive.i +++ b/Examples/test-suite/constant_directive.i @@ -1,28 +1,41 @@ %module constant_directive // %constant and struct + +%inline %{ +struct Type1 { + Type1(int val = 0) : val(val) {} + int val; +}; +/* Typedefs for const Type and its pointer */ +typedef const Type1 Type1Const; +typedef const Type1* Type1Cptr; + +/* Typedefs for function pointers returning Type1 */ +typedef Type1 (*Type1Fptr)(); +typedef Type1 (* const Type1Cfptr)(); + +/* Function returning an instance of Type1 */ +Type1 getType1Instance() { return Type1(111); } +%} + %{ - struct Type1 { - Type1(int val = 0) : val(val) {} - int val; - }; static Type1 TYPE1_CONSTANT1(1); static Type1 TYPE1_CONST2(2); static Type1 TYPE1_CONST3(3); %} -struct Type1 { - Type1(int val = 0) : val(val) {} - int val; -}; - -%inline %{ -Type1 getType1Instance() { return Type1(111); } -%} - %constant Type1 TYPE1_CONSTANT1; %constant Type1 TYPE1_CONSTANT2 = TYPE1_CONST2; %constant Type1 *TYPE1_CONSTANT3 = &TYPE1_CONST3; - +/* Typedef'ed types */ +%constant Type1Const* TYPE1CONST_CONSTANT1 = &TYPE1_CONSTANT1; +%constant Type1Cptr TYPE1CPTR_CONSTANT1 = &TYPE1_CONSTANT1; +/* Function pointers */ +%constant Type1 (*TYPE1FPTR1_CONSTANT1)() = getType1Instance; +%constant Type1 (* const TYPE1CFPTR1_CONSTANT1)() = getType1Instance; +/* Typedef'ed function pointers */ +%constant Type1Fptr TYPE1FPTR1DEF_CONSTANT1 = getType1Instance; +%constant Type1Cfptr TYPE1CFPTR1DEF_CONSTANT1 = getType1Instance; +/* Regular constant */ %constant int TYPE_INT = 0; - diff --git a/Examples/test-suite/java/constant_directive_runme.java b/Examples/test-suite/java/constant_directive_runme.java index b5135a499..4b5c3c3d0 100644 --- a/Examples/test-suite/java/constant_directive_runme.java +++ b/Examples/test-suite/java/constant_directive_runme.java @@ -18,5 +18,9 @@ public class constant_directive_runme { throw new RuntimeException("fail"); if (constant_directive.TYPE1_CONSTANT3.getVal() != 3) throw new RuntimeException("fail"); + if (constant_directive.TYPE1CONST_CONSTANT1.getVal() != 1) + throw new RuntimeException("fail"); + if (constant_directive.TYPE1CPTR_CONSTANT1.getVal() != 1) + throw new RuntimeException("fail"); } } diff --git a/Examples/test-suite/python/constant_directive_runme.py b/Examples/test-suite/python/constant_directive_runme.py index a7ed82b8b..e223cd261 100644 --- a/Examples/test-suite/python/constant_directive_runme.py +++ b/Examples/test-suite/python/constant_directive_runme.py @@ -18,3 +18,11 @@ if constant_directive.TYPE1_CONSTANT2.val != 2: if constant_directive.TYPE1_CONSTANT3.val != 3: raise RuntimeError("constant_directive.TYPE1_CONSTANT3.val is %r (should be 3)" % constant_directive.TYPE1_CONSTANT3.val) + +if constant_directive.TYPE1CONST_CONSTANT1.val != 1: + raise RuntimeError("constant_directive.TYPE1CONST_CONSTANT1.val is %r (should be 1)" % + constant_directive.TYPE1CONST_CONSTANT1.val) + +if constant_directive.TYPE1CPTR_CONSTANT1.val != 1: + raise RuntimeError("constant_directive.TYPE1CPTR_CONSTANT1.val is %r (should be 1)" % + constant_directive.TYPE1CPTR_CONSTANT1.val) diff --git a/Lib/python/pytypemaps.swg b/Lib/python/pytypemaps.swg index 2341980f2..48b0bcdc8 100644 --- a/Lib/python/pytypemaps.swg +++ b/Lib/python/pytypemaps.swg @@ -79,10 +79,12 @@ /* Consttab, needed for callbacks, it should be removed later */ -%typemap(consttab) SWIGTYPE ((*)(ANY)) +%typemap(consttab) SWIGTYPE ((*)(ANY)) { SWIG_PY_POINTER, (char*)"$symname", 0, 0, (void *)($value), &$descriptor } +%typemap(consttab) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY)); %typemap(constcode) SWIGTYPE ((*)(ANY)) ""; +%typemap(constcode) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY)); /* Smart Pointers */ diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index e8124df9c..40d3ff5e9 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -625,6 +625,7 @@ %typemap(constcode, noblock=1) SWIGTYPE ((*)(ANY)){ %set_constant("$symname", SWIG_NewFunctionPtrObj((void *)$value, $descriptor)); } +%typemap(constcode) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY)); #if defined(SWIG_DIRECTOR_TYPEMAPS) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index ce3b55209..1c11801e2 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -3454,19 +3454,37 @@ public: * constantWrapper() * ------------------------------------------------------------ */ + /* Determine if the node requires the _swigconstant code to be generated */ + bool needs_swigconstant(Node* n) { + SwigType *type = Getattr(n, "type"); + SwigType *qtype = SwigType_typedef_resolve_all(type); + SwigType *uqtype = SwigType_strip_qualifiers(qtype); + bool result = false; + + /* Note, that we need special handling for function pointers, as + * SwigType_base(fptr) does not return the underlying pointer-to-function + * type but the return-type of function. */ + if(!SwigType_isfunction(uqtype) && !SwigType_isfunctionpointer(uqtype)) { + SwigType *basetype = SwigType_base(uqtype); + result = (bool)SwigType_isclass(basetype); + Delete(basetype); + } + + Delete(qtype); + Delete(uqtype); + + return result; + } + virtual int constantWrapper(Node *n) { String *name = Getattr(n, "name"); String *iname = Getattr(n, "sym:name"); SwigType *type = Getattr(n, "type"); - SwigType *basetype = SwigType_base(type); String *rawval = Getattr(n, "rawval"); String *value = rawval ? rawval : Getattr(n, "value"); String *tm; int have_tm = 0; int have_builtin_symname = 0; - int is_classobj = SwigType_isclass(basetype); - - Delete(basetype); if (!addSymbol(iname, n)) return SWIG_ERROR; @@ -3500,7 +3518,7 @@ public: Replaceall(tm, "$source", value); Replaceall(tm, "$target", name); Replaceall(tm, "$value", value); - if (is_classobj && !builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER)) && (!in_class || !Getattr(n, "feature:python:callback"))) { + if (needs_swigconstant(n) && !builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER)) && (!in_class || !Getattr(n, "feature:python:callback"))) { // Generate `*_swigconstant()` method which registers the new constant. // // *_swigconstant methods are required for constants of class type. @@ -3548,14 +3566,14 @@ public: if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { if (!in_class) { - if(is_classobj) { + if(needs_swigconstant(n)) { Printv(f_shadow, "\n",NIL); Printv(f_shadow, module, ".", iname, "_swigconstant(",module,")\n", NIL); } Printv(f_shadow, iname, " = ", module, ".", iname, "\n", NIL); } else { if (!(Getattr(n, "feature:python:callback"))) { - if(is_classobj) { + if(needs_swigconstant(n)) { Printv(f_shadow_stubs, "\n",NIL); Printv(f_shadow_stubs, module, ".", iname, "_swigconstant(", module, ")\n", NIL); }