From 96015de0dd600da5ec0431d04a7eb2f2c5dd9a96 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 22 Oct 2016 20:55:37 +0100 Subject: [PATCH] Update documentation for using SWIG_ConvertPtr example usage Add a test case to test the example documentation typemaps --- Doc/Manual/Lua.html | 2 +- Doc/Manual/Perl5.html | 12 +++- Doc/Manual/Python.html | 16 +++-- Doc/Manual/Tcl.html | 12 +++- Doc/Manual/Typemaps.html | 66 ++++++++----------- Examples/test-suite/common.mk | 1 + .../python/typemap_documentation_runme.py | 20 ++++++ Examples/test-suite/typemap_documentation.i | 50 ++++++++++++++ 8 files changed, 125 insertions(+), 54 deletions(-) create mode 100644 Examples/test-suite/python/typemap_documentation_runme.py create mode 100644 Examples/test-suite/typemap_documentation.i diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index 032d05dba..131d92825 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -1740,7 +1740,7 @@ ptr=nil -- the iMath* will be GC'ed as normal
This is the standard function used for converting a Lua userdata to a void*. It takes the value at the given index in the Lua state and converts it to a userdata. It will then provide the necessary type checks, confirming that the pointer is compatible with the type given in 'type'. Then finally setting '*ptr' to the pointer. If flags is set to SWIG_POINTER_DISOWN, this is will clear any ownership flag set on the object.
-The returns a value which can be checked with the macro SWIG_IsOK() +This returns a value which can be checked with the macro SWIG_IsOK()

void SWIG_NewPointerObj(lua_State* L,void* ptr,swig_type_info *type,int own);

diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 19747c3dc..4722a01ba 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -2477,7 +2477,9 @@ is usually accessed as follows:
 Foo *f;
-if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL;
+if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
+  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+}
 
 SV *sv = sv_newmortal();
 SWIG_MakePtr(sv, f, SWIGTYPE_p_Foo, 0);
@@ -2492,7 +2494,9 @@ variable $1_descriptor.  For example:
 
 %typemap(in) Foo * {
-  if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
@@ -2505,7 +2509,9 @@ For example:
 %typemap(in) Foo * {
-  if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 30aa82115..b6df0895f 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -5208,8 +5208,9 @@ is usually accessed as follows:
 Foo *f;
-if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, SWIG_POINTER_EXCEPTION) == -1)
-  return NULL;
+if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
+  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+}
 
 PyObject *obj;
 obj = SWIG_NewPointerObj(f, SWIGTYPE_p_Foo, 0);
@@ -5224,8 +5225,9 @@ variable $1_descriptor.  For example:
 
 %typemap(in) Foo * {
-if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,SWIG_POINTER_EXCEPTION)) == -1)
-  return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
@@ -5238,9 +5240,9 @@ For example:
 %typemap(in) Foo * {
-if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 
-                                               SWIG_POINTER_EXCEPTION)) == -1)
-  return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index b07f99b69..af4880217 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -3088,7 +3088,9 @@ is usually accessed as follows:
 Foo *f;
-if (SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0) == -1) return NULL;
+if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &f, SWIGTYPE_p_Foo, 0))) {
+  SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+}
 
 Tcl_Obj *;
 obj = SWIG_NewPointerObj(f, SWIGTYPE_p_Foo, 0);
@@ -3103,7 +3105,9 @@ variable $1_descriptor.  For example:
 
 %typemap(in) Foo * {
-  if ((SWIG_ConvertPtr($input,(void **) &$1, $1_descriptor,0)) == -1) return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
@@ -3116,7 +3120,9 @@ For example:
 %typemap(in) Foo * {
-  if ((SWIG_ConvertPtr($input,(void **) &$1, $descriptor(Foo *), 0)) == -1) return NULL;
+  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $descriptor(Foo *), 0))) {
+    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
+  }
 }
 
diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index f83a26949..8aa5abb3f 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -489,7 +489,7 @@ int foo(int x, double y, char *s);
  • Input argument conversion ("in" typemap).
  • -
  • Input argument type checking ("typecheck" typemap).
  • +
  • Input argument type checking for types used in overloaded methods ("typecheck" typemap).
  • Output argument handling ("argout" typemap).
  • Input argument value checking ("check" typemap).
  • Input argument initialization ("arginit" typemap).
  • @@ -2586,6 +2586,7 @@ to see whether or not it matches a specific type. For example:

    For typechecking, the $1 variable is always a simple integer that is set to 1 or 0 depending on whether or not the input argument is the correct type. +Set to 1 if the input argument is the correct type otherwise set to 0.

    @@ -4138,14 +4139,17 @@ For example:

     class Foo {
    +public:
       int x;
     };
     
     class Bar {
    +public:
       int y;
     };
     
     class FooBar : public Foo, public Bar {
    +public:
       int z;
     };
     
    @@ -4180,12 +4184,15 @@ handling of pointer values (and to make adjustments when needed).

    In the wrapper code generated for each language, pointers are handled through the use of special type descriptors and conversion functions. For example, -if you look at the wrapper code for Python, you will see code like this: +if you look at the wrapper code for Python, you will see code similar to the following +(simplified for brevity):

    -if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Foo,1)) == -1) return NULL;
    +if (!SWIG_IsOK(SWIG_ConvertPtr(obj0, (void **) &arg1, SWIGTYPE_p_Foo, 0))) {
    +  SWIG_exception_fail(SWIG_TypeError, "in method 'GrabVal', expecting type Foo");
    +}
     
    @@ -4197,8 +4204,10 @@ target language, a list of equivalent typenames (via typedef or inheritance), and pointer value handling information (if applicable). The SWIG_ConvertPtr() function is simply a utility function that takes a pointer object in the target language and a -type-descriptor objects and uses this information to generate a C++ -pointer. However, the exact name and calling conventions of the conversion +type-descriptor object and uses this information to generate a C++ pointer. +The SWIG_IsOK macro checks the return value for errors and +SWIG_exception_fail can be called to raise an exception in the target language. +However, the exact name and calling conventions of the conversion function depends on the target language (see language specific chapters for details).

    @@ -4304,7 +4313,9 @@ similar to this:
     %typemap(in) Foo * {
    -  if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) return NULL;
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
    +    SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo");
    +  }
     }
     
    @@ -4337,12 +4348,12 @@ descriptor name for any C datatype. For example:
     %typemap(in) Foo * {
    -  if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) {
    +  if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) {
         Bar *temp;
    -    if ((SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *)) == -1) {
    -      return NULL;
    +    if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *), 0))) {
    +      SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo or Bar");
         }
    -    $1 = (Foo *) temp;
    +    $1 = (Foo *)temp;
       }
     }
     
    @@ -4588,38 +4599,13 @@ The following excerpt from the Python module illustrates this: $1 = PyString_Check($input) ? 1 : 0; } -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] { - void *ptr; - if (SWIG_ConvertPtr($input, (void **) &ptr, $1_descriptor, 0) == -1) { - $1 = 0; - PyErr_Clear(); - } else { - $1 = 1; - } +%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE * { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $1_descriptor, 0); + $1 = SWIG_IsOK(res) ? 1 : 0; } -%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { - void *ptr; - if (SWIG_ConvertPtr($input, (void **) &ptr, $&1_descriptor, 0) == -1) { - $1 = 0; - PyErr_Clear(); - } else { - $1 = 1; - } -} - -%typecheck(SWIG_TYPECHECK_VOIDPTR) void * { - void *ptr; - if (SWIG_ConvertPtr($input, (void **) &ptr, 0, 0) == -1) { - $1 = 0; - PyErr_Clear(); - } else { - $1 = 1; - } -} - -%typecheck(SWIG_TYPECHECK_POINTER) PyObject * -{ +%typecheck(SWIG_TYPECHECK_POINTER) PyObject * { $1 = ($input != 0); }
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index b9ba746bb..c6a02f487 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -487,6 +487,7 @@ CPP_TEST_CASES += \ typemap_array_qualifiers \ typemap_delete \ typemap_directorout \ + typemap_documentation \ typemap_global_scope \ typemap_manyargs \ typemap_namespace \ diff --git a/Examples/test-suite/python/typemap_documentation_runme.py b/Examples/test-suite/python/typemap_documentation_runme.py new file mode 100644 index 000000000..3d1c6fa8c --- /dev/null +++ b/Examples/test-suite/python/typemap_documentation_runme.py @@ -0,0 +1,20 @@ +import typemap_documentation + +f = typemap_documentation.Foo() +f.x = 55 +b = typemap_documentation.Bar() +b.y = 44 + +if 55 != typemap_documentation.GrabVal(f): + raise RuntimeError("bad value") + +try: + typemap_documentation.GrabVal(b) + raise RuntimeError("unexpected exception") +except TypeError: + pass + +if 55 != typemap_documentation.GrabValFooBar(f): + raise RuntimeError("bad f value") +if 44 != typemap_documentation.GrabValFooBar(b): + raise RuntimeError("bad b value") diff --git a/Examples/test-suite/typemap_documentation.i b/Examples/test-suite/typemap_documentation.i new file mode 100644 index 000000000..b7c1ddd22 --- /dev/null +++ b/Examples/test-suite/typemap_documentation.i @@ -0,0 +1,50 @@ +%module typemap_documentation + +// A place for checking that documented typemaps are working. +// The UTL languages are the only ones that are consistent enough to support these generic typemap functions. +// These are in the Typemaps.html chapter. + +%inline %{ +class Foo { +public: + int x; +}; + +class Bar { +public: + int y; +}; +%} + +#if defined(SWIGUTL) +%typemap(in) Foo * { + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) { + SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo"); + } +} +#endif + +%inline %{ +int GrabVal(Foo *f) { + return f->x; +} +%} + + +#if defined(SWIGUTL) +%typemap(in) Foo * { + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0))) { + Bar *temp; + if (!SWIG_IsOK(SWIG_ConvertPtr($input, (void **) &temp, $descriptor(Bar *), 0))) { + SWIG_exception_fail(SWIG_TypeError, "in method '$symname', expecting type Foo or Bar"); + } + $1 = (Foo *)temp; + } +} +#endif + +%inline %{ +int GrabValFooBar(Foo *f) { + return f->x; +} +%}