diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index ccab1f429..b287c2a1a 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -413,6 +413,7 @@ int foo(int x, double y, char *s);
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) int {
+ $1 = PyInt_Check($input) ? 1 : 0;
+}
+
+
+
+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.
+
++If you define new "in" typemaps and your program uses overloaded methods, you should also define a collection of +"typecheck" typemaps. More details about this follow in a later section on "Typemaps and Overloading." +
++ +You can access the functions in a normal way from the scripting interpreter: + ++int foo(int x); +int foo(double x); +int foo(char *s, int y); ++
+
+# Python
+foo(3) # foo(int)
+foo(3.5) # foo(double)
+foo("hello",5) # foo(char *, int)
+
+# Tcl
+foo 3 # foo(int)
+foo 3.5 # foo(double)
+foo hello 5 # foo(char *, int)
+
+
+
+To implement overloading, SWIG generates a separate wrapper function for each overloaded method.
+For example, the above functions would produce something roughly like this:
+
+
+
+// wrapper pseudocode
+_wrap_foo_0(argc, args[]) { // foo(int)
+ int arg1;
+ int result;
+ ...
+ arg1 = FromInteger(args[0]);
+ result = foo(arg1);
+ return ToInteger(result);
+}
+
+_wrap_foo_1(argc, args[]) { // foo(double)
+ double arg1;
+ int result;
+ ...
+ arg1 = FromDouble(args[0]);
+ result = foo(arg1);
+ return ToInteger(result);
+}
+
+_wrap_foo_2(argc, args[]) { // foo(char *, int)
+ char *arg1;
+ int arg2;
+ int result;
+ ...
+ arg1 = FromString(args[0]);
+ arg2 = FromInteger(args[1]);
+ result = foo(arg1,arg2);
+ return ToInteger(result);
+}
+
+
+
+
+Next, a dynamic dispatch function is generated:
+
+
+
+_wrap_foo(argc, args[]) {
+ if (argc == 1) {
+ if (IsInteger(args[0])) {
+ return _wrap_foo_0(argc,args);
+ }
+ if (IsDouble(args[0])) {
+ return _wrap_foo_1(argc,args);
+ }
+ }
+ if (argc == 2) {
+ if (IsString(args[0]) && IsInteger(args[1])) {
+ return _wrap_foo_2(argc,args);
+ }
+ }
+ error("No matching function!\n");
+}
+
+
+
+The purpose of the dynamic dispatch function is to select the appropriate C++ function based on
+argument types---a task that must be performed at runtime in most of SWIG's target languages.
+
++The generation of the dynamic dispatch function is a relatively tricky affair. Not only must input typemaps +be taken into account (these typemaps can radically change the types of arguments accepted), but overloaded +methods must also be sorted and checked in a very specific order to resolve potential ambiguity. A high-level +overview of this ranking process is found in the "SWIG and C++" chapter. What isn't mentioned in that chapter +is the mechanism by which it is implemented---as a collection of typemaps. + +
+To support dynamic dispatch, SWIG first defines a general purpose type hierarchy as follows: + +
++ +(These precedence levels are defined in swig.swg, a library file that's included by all target language modules.) + ++Symbolic Name Precedence Value +------------------------------ ------------------ +SWIG_TYPECHECK_POINTER 0 +SWIG_TYPECHECK_VOIDPTR 10 +SWIG_TYPECHECK_BOOL 15 +SWIG_TYPECHECK_UINT8 20 +SWIG_TYPECHECK_INT8 25 +SWIG_TYPECHECK_UINT16 30 +SWIG_TYPECHECK_INT16 35 +SWIG_TYPECHECK_UINT32 40 +SWIG_TYPECHECK_INT32 45 +SWIG_TYPECHECK_UINT64 50 +SWIG_TYPECHECK_INT64 55 +SWIG_TYPECHECK_UINT128 60 +SWIG_TYPECHECK_INT128 65 +SWIG_TYPECHECK_INTEGER 70 +SWIG_TYPECHECK_FLOAT 80 +SWIG_TYPECHECK_DOUBLE 90 +SWIG_TYPECHECK_COMPLEX 100 +SWIG_TYPECHECK_UNICHAR 110 +SWIG_TYPECHECK_UNISTRING 120 +SWIG_TYPECHECK_CHAR 130 +SWIG_TYPECHECK_STRING 140 +SWIG_TYPECHECK_BOOL_ARRAY 1015 +SWIG_TYPECHECK_INT8_ARRAY 1025 +SWIG_TYPECHECK_INT16_ARRAY 1035 +SWIG_TYPECHECK_INT32_ARRAY 1045 +SWIG_TYPECHECK_INT64_ARRAY 1055 +SWIG_TYPECHECK_INT128_ARRAY 1065 +SWIG_TYPECHECK_FLOAT_ARRAY 1080 +SWIG_TYPECHECK_DOUBLE_ARRAY 1090 +SWIG_TYPECHECK_CHAR_ARRAY 1130 +SWIG_TYPECHECK_STRING_ARRAY 1140 ++
+In this table, the precedence-level determines the order in which types are going to be checked. Low values +are always checked before higher values. For example, integers are checked before floats, single values are checked +before arrays, and so forth. + +
+Using the above table as a guide, each target language defines a collection of "typecheck" typemaps. +The follow excerpt from the Python module illustrates this: + +
+
+/* Python type checking rules */
+/* Note: %typecheck(X) is a macro for %typemap(typecheck,precedence=X) */
+
+%typecheck(SWIG_TYPECHECK_INTEGER)
+ int, short, long,
+ unsigned int, unsigned short, unsigned long,
+ signed char, unsigned char,
+ long long, unsigned long long,
+ const int &, const short &, const long &,
+ const unsigned int &, const unsigned short &, const unsigned long &,
+ const long long &, const unsigned long long &,
+ enum SWIGTYPE,
+ bool, const bool &
+{
+ $1 = (PyInt_Check($input) || PyLong_Check($input)) ? 1 : 0;
+}
+
+%typecheck(SWIG_TYPECHECK_DOUBLE)
+ float, double,
+ const float &, const double &
+{
+ $1 = (PyFloat_Check($input) || PyInt_Check($input) || PyLong_Check($input)) ? 1 : 0;
+}
+
+%typecheck(SWIG_TYPECHECK_CHAR) char {
+ $1 = (PyString_Check($input) && (PyString_Size($input) == 1)) ? 1 : 0;
+}
+
+%typecheck(SWIG_TYPECHECK_STRING) char * {
+ $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;
+ }
+}
+
+%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 *
+{
+ $1 = ($input != 0);
+}
+
+
+
+It might take a bit of contemplation, but this code has merely organized all of the basic C++ types, provided some simple type-checking
+code, and assigned each type a precedence value.
+
++Finally, to generate the dynamic dispatch function, SWIG uses the following algorithm: + +
+
+// Typemap for a C++ string
+%typemap(in) std::string {
+ if (PyString_Check($input)) {
+ $1 = std::string(PyString_AsString($input));
+ } else {
+ SWIG_exception(SWIG_TypeError, "string expected");
+ }
+}
+// Copy the typecheck code for "char *".
+%typemap(typecheck) std::string = char *;
+
+
+
+The bottom line: If you are writing new typemaps and you are using overloaded methods, you will probably
+have to write typecheck code or copy existing code. Since this is a relatively new SWIG feature, there are
+few examples to work with. However, you might look at some of the existing library files likes 'typemaps.i' for
+a guide.
+
++Notes: + +
+
+
+