Index: swig/Lib/typemaps/fragments.swg |
=================================================================== |
--- swig/Lib/typemaps/fragments.swg (revision 0) |
+++ swig/Lib/typemaps/fragments.swg (revision 0) |
@@ -0,0 +1,458 @@ |
+/* |
+ Fragments: |
+ ========== |
+ |
+ Second to typemaps, fragments are one the most powerful and |
+ dangerous swig features. So, if you are starting to read about them, |
+ make sure you read all of this document. |
+ |
+ Basics: |
+ ======= |
+ |
+ Fragments provide a way to include or generate code into "on-demand" |
+ as the typemaps could require. |
+ |
+ For example, if you have a very long typemap |
+ |
+ %typemap(in) MyClass * { |
+ MyClass *value = 0; |
+ |
+ <very long typemap> |
+ .... |
+ value = somewhere_converted_from_input_object_here($input); |
+ ... |
+ <very long typemap> |
+ |
+ $result = value; |
+ } |
+ |
+ very soon you will discover yourself copying the same long |
+ conversion code in several typemaps, such as varin, directorout, |
+ etc. Also, you will discover that swig copes verbatim the same very |
+ long conversion code for every argument that requires it, making the |
+ code very large too. |
+ |
+ To eliminate this automatic or manual code copying, we define a |
+ fragment that includes the common conversion code: |
+ |
+ %fragment("AsMyClass","header") { |
+ MyClass *AsMyClass(PyObject *obj) { |
+ MyClass *value = 0; |
+ <very long conversion> |
+ .... |
+ value = somewhere_converted_from_input_object_here(obj); |
+ ... |
+ <very long conversion> |
+ |
+ return value; |
+ } |
+ } |
+ |
+ %typemap(in,fragment="AsMyClass") MyClass * { |
+ $result = AsMyClass($input); |
+ } |
+ |
+ %typemap(varin,fragment="AsMyClass") MyClass * { |
+ $result = AsMyClass($input); |
+ } |
+ |
+ When the 'in' or 'varin' typemaps for MyClass are invoked, the |
+ fragment "AsMyClass" is added to the "header" section, and then the |
+ typemap code is emitted. Hence, the method AsMyClass will be |
+ included in the wrapping code and it will be available at the time |
+ the typemap is applied. |
+ |
+ To define a fragment then you need a name, a section where it goes, |
+ and the code. Usually the section refers to the "header" part, and |
+ both string and braces forms are accepted, ie: |
+ |
+ %fragment("my_name","header") { ... } |
+ %fragment("my_name","header") "..."; |
+ |
+ To ensure all the fragment/typemap engine works as expected, there |
+ are some rules that fragments follow: |
+ |
+ 1.- A fragment is added to the wrapping code only once, ie, for the |
+ method: |
+ |
+ int foo(MyClass *a, MyClass *b); |
+ |
+ the wrapped code will look as much as: |
+ |
+ MyClass *AsMyClass(PyObject *obj) { |
+ ..... |
+ } |
+ |
+ int _wrap_foo(...) { |
+ .... |
+ arg1 = AsMyClass(obj1); |
+ arg2 = AsMyClass(obj2); |
+ ... |
+ result = foo(arg1, arg2); |
+ } |
+ |
+ |
+ even when there will be duplicated typemap to process 'a' and |
+ 'b', the 'AsMyClass' method will be defined only once. |
+ |
+ |
+ 2.- A fragment can only defined once, and the first definition |
+ is the only one taking in account. All other definitions of the |
+ same fragments are silently ignored. For example, you can have |
+ |
+ |
+ %fragment("AsMyClass","header") { <definition 1> } |
+ .... |
+ %fragment("AsMyClass","header") { <definition 2> } |
+ |
+ and then only the first definition is considered. In this way |
+ you can change the 'system' fragments by including yours first. |
+ |
+ Note that this behavior is opposite to the typemaps, where the |
+ last typemap applied or defined prevails. Fragment follows the |
+ first-in-first-out convention since they are intended to be |
+ "global", while typemaps intend to be "locally" specialized. |
+ |
+ 3.- Fragments names can not contain commas. |
+ |
+ |
+ A fragment can include one or more additional fragments, for example: |
+ |
+ %fragment("<limits.h>", "header") { |
+ #include <limits.h> |
+ } |
+ |
+ |
+ %fragment("AsMyClass", "header", fragment="<limits.h>") { |
+ MyClass *AsMyClass(PyObject *obj) { |
+ MyClass *value = 0; |
+ int ival = somewhere_converted_from_input_object_here(obj) |
+ ... |
+ if (ival < CHAR_MIN) { |
+ value = something_from_ival(ival); |
+ } else { |
+ ... |
+ } |
+ ... |
+ return value; |
+ } |
+ } |
+ |
+ in this case, when the "AsMyClass" fragment is emitted, it also |
+ trigger the inclusion of the "<limits.h>" fragment. |
+ |
+ You can add as many fragments as you want, for example |
+ |
+ %fragment("bigfragment","header", fragment="frag1", fragment="frag2", fragment="frag3") ""; |
+ |
+ here, when the "bigfragment" is included, the three fragments "frag1", |
+ "frag2" and "frag3" are included. Note that as "bigframent" is defined |
+ empty, "", it does not add any code by itself, buy only trigger the |
+ inclusion of the other fragments. |
+ |
+ In a typemap you can also include more than one fragment, but since the |
+ syntax is different, you need to specify them in a 'comma separated' |
+ list, for example, considering the previous example: |
+ |
+ %typemap(in,fragment="frag1,frag2,frag3") {...} |
+ |
+ is equivalent to |
+ |
+ %typemap(in,fragment="bigfragment") {...} |
+ |
+ |
+ Finally, you can force the inclusion of a fragment at any moment as follow: |
+ |
+ %fragment("bigfragment"); |
+ |
+ which is very useful inside a template class, for example. |
+ |
+ |
+ Fragment type specialization |
+ ============================ |
+ |
+ Fragments can be "type specialized". The syntax is as follows |
+ |
+ %fragment("name","header") { a type independent fragment } |
+ %fragment("name" {Type}, "header") { a type dependent fragment } |
+ |
+ and they can also, as typemaps, be used inside templates, for exampe: |
+ |
+ template <class T> |
+ struct A { |
+ %fragment("incode"{A<T>},"header") { |
+ 'incode' specialized fragment |
+ } |
+ |
+ %typemap(in,fragment="incode"{A<T>}) { |
+ here we use the 'type specialized' |
+ fragment "incode"{A<T>} |
+ } |
+ }; |
+ |
+ which could seems a not much interesting feature, but is |
+ fundamental for automatic typemap and template specialization. |
+ |
+ |
+ Fragments and automatic typemap specialization: |
+ =============================================== |
+ |
+ Since fragments can be type specialized, they can be elegantly used |
+ to specialized typemaps . |
+ |
+ For example, if you have something like: |
+ |
+ %fragment("incode"{float}, "header") { |
+ float in_method_float(PyObject *obj) { |
+ ... |
+ } |
+ } |
+ |
+ %fragment("incode"{long}, "header") { |
+ float in_method_long(PyObject *obj) { |
+ ... |
+ } |
+ } |
+ |
+ %define %my_typemaps(Type) |
+ %typemaps(in,fragment="incode"{Type}) { |
+ value = in_method_##Type(obj); |
+ } |
+ %enddef |
+ |
+ %my_typemaps(float); |
+ %my_typemaps(long); |
+ |
+ then the proper "incode"{float,double} fragment will be included, |
+ and the proper in_method_{float,double} will be called. |
+ |
+ Since this is a recurrent fragment use, we provide a couple of |
+ macros that make the automatic generation of typemaps easier: |
+ |
+ |
+ Consider for example the following code: |
+ |
+ %fragment(SWIG_From_frag(bool),"header") { |
+ static PyObject* |
+ SWIG_From_dec(bool)(bool value) |
+ { |
+ PyObject *obj = value ? Py_True : Py_False; |
+ Py_INCREF(obj); |
+ return obj; |
+ } |
+ } |
+ |
+ %typemap(out,fragment=SWIG_From_frag(bool)) bool { |
+ $result = SWIG_From(bool)($1)); |
+ } |
+ |
+ Here the macros |
+ |
+ SWIG_From_frag => fragment |
+ SWIG_From_dec => declaration |
+ SWIG_From => call |
+ |
+ allow you to define/include a fragment, and declare and call the |
+ 'from-bool' method as needed. In the simpler case, these macros |
+ just return something like |
+ |
+ SWIG_From_frag(bool) => "SWIG_From_bool" |
+ SWIG_From_dec(bool) => SWIG_From_bool |
+ SWIG_From(bool) => SWIG_From_bool |
+ |
+ But they are specialized for the different languages requirements, |
+ such as perl or tcl that requires passing the interpreter pointer, |
+ and also they can manage C++ ugly types, for example: |
+ |
+ SWIG_From_frag(std::complex<double>) => "SWIG_From_std_complex_Sl_double_Sg_" |
+ SWIG_From_dec(std::complex<double>) => SWIG_From_std_complex_Sl_double_Sg_ |
+ SWIG_From(std::complex<double>) => SWIG_From_std_complex_Sl_double_Sg_ |
+ |
+ |
+ Hence, to declare methods to use with typemaps, always use the |
+ SWIG_From* macros. In the same way, the SWIG_AsVal* and SWIG_AsPtr* |
+ set of macros are provided. |
+ |
+*/ |
+ |
+ |
+/* ----------------------------------------------------------------------------- |
+ * Define the basic macros to 'normalize' the type fragments |
+ * ----------------------------------------------------------------------------- */ |
+ |
+#ifndef SWIG_AS_DECL_ARGS |
+#define SWIG_AS_DECL_ARGS |
+#endif |
+ |
+#ifndef SWIG_FROM_DECL_ARGS |
+#define SWIG_FROM_DECL_ARGS |
+#endif |
+ |
+#ifndef SWIG_AS_CALL_ARGS |
+#define SWIG_AS_CALL_ARGS |
+#endif |
+ |
+#ifndef SWIG_FROM_CALL_ARGS |
+#define SWIG_FROM_CALL_ARGS |
+#endif |
+ |
+#define %fragment_name(Name, Type...) %string_name(Name) "_" {Type} |
+ |
+#define SWIG_Traits_frag(Type...) %fragment_name(Traits, Type) |
+#define SWIG_AsPtr_frag(Type...) %fragment_name(AsPtr, Type) |
+#define SWIG_AsVal_frag(Type...) %fragment_name(AsVal, Type) |
+#define SWIG_From_frag(Type...) %fragment_name(From, Type) |
+ |
+#define SWIG_AsVal_name(Type...) %symbol_name(AsVal, Type) |
+#define SWIG_AsPtr_name(Type...) %symbol_name(AsPtr, Type) |
+#define SWIG_From_name(Type...) %symbol_name(From, Type) |
+ |
+#define SWIG_AsVal_dec(Type...) SWIG_AsVal_name(Type) SWIG_AS_DECL_ARGS |
+#define SWIG_AsPtr_dec(Type...) SWIG_AsPtr_name(Type) SWIG_AS_DECL_ARGS |
+#define SWIG_From_dec(Type...) SWIG_From_name(Type) SWIG_FROM_DECL_ARGS |
+ |
+#define SWIG_AsVal(Type...) SWIG_AsVal_name(Type) SWIG_AS_CALL_ARGS |
+#define SWIG_AsPtr(Type...) SWIG_AsPtr_name(Type) SWIG_AS_CALL_ARGS |
+#define SWIG_From(Type...) SWIG_From_name(Type) SWIG_FROM_CALL_ARGS |
+ |
+/* ------------------------------------------------------------ |
+ * common fragments |
+ * ------------------------------------------------------------ */ |
+ |
+/* Default compiler options for gcc allow long_long but not LLONG_MAX. |
+ * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */ |
+%fragment("<limits.h>","header") %{ |
+#include <limits.h> |
+#if !defined(SWIG_NO_LLONG_MAX) |
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) |
+# define LLONG_MAX __LONG_LONG_MAX__ |
+# define LLONG_MIN (-LLONG_MAX - 1LL) |
+# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) |
+# endif |
+#endif |
+%} |
+ |
+%fragment("<math.h>","header") %{ |
+#include <math.h> |
+%} |
+ |
+%fragment("<wchar.h>","header") %{ |
+#include <wchar.h> |
+#include <limits.h> |
+#ifndef WCHAR_MIN |
+# define WCHAR_MIN 0 |
+#endif |
+#ifndef WCHAR_MAX |
+# define WCHAR_MAX 65535 |
+#endif |
+%} |
+ |
+%fragment("<float.h>","header") %{ |
+#include <float.h> |
+%} |
+ |
+%fragment("<stdio.h>","header") %{ |
+#include <stdio.h> |
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) |
+# ifndef snprintf |
+# define snprintf _snprintf |
+# endif |
+#endif |
+%} |
+ |
+%fragment("<stdlib.h>","header") %{ |
+#include <stdlib.h> |
+#ifdef _MSC_VER |
+# ifndef strtoull |
+# define strtoull _strtoui64 |
+# endif |
+# ifndef strtoll |
+# define strtoll _strtoi64 |
+# endif |
+#endif |
+%} |
+ |
+/* ----------------------------------------------------------------------------- |
+ * special macros for fragments |
+ * ----------------------------------------------------------------------------- */ |
+ |
+/* Macros to derive numeric types */ |
+ |
+%define %numeric_type_from(Type, Base) |
+%fragment(SWIG_From_frag(Type),"header", |
+ fragment=SWIG_From_frag(Base)) { |
+SWIGINTERNINLINE SWIG_Object |
+SWIG_From_dec(Type)(Type value) |
+{ |
+ return SWIG_From(Base)(value); |
+} |
+} |
+%enddef |
+ |
+%define %numeric_type_asval(Type, Base, Frag, OverflowCond) |
+%fragment(SWIG_AsVal_frag(Type),"header", |
+ fragment=Frag, |
+ fragment=SWIG_AsVal_frag(Base)) { |
+SWIGINTERN int |
+SWIG_AsVal_dec(Type)(SWIG_Object obj, Type *val) |
+{ |
+ Base v; |
+ int res = SWIG_AsVal(Base)(obj, &v); |
+ if (SWIG_IsOK(res)) { |
+ if (OverflowCond) { |
+ return SWIG_OverflowError; |
+ } else { |
+ if (val) *val = %numeric_cast(v, Type); |
+ } |
+ } |
+ return res; |
+} |
+} |
+%enddef |
+ |
+#define %numeric_signed_type_asval(Type, Base, Frag, Min, Max) \ |
+%numeric_type_asval(Type, Base, Frag, (v < Min || v > Max)) |
+ |
+#define %numeric_unsigned_type_asval(Type, Base, Frag, Max) \ |
+%numeric_type_asval(Type, Base, Frag, (v > Max)) |
+ |
+ |
+/* Macro for 'signed long' derived types */ |
+ |
+%define %numeric_slong(Type, Frag, Min, Max) |
+%numeric_type_from(Type, long) |
+%numeric_signed_type_asval(Type, long, Frag , Min, Max) |
+%enddef |
+ |
+/* Macro for 'unsigned long' derived types */ |
+ |
+%define %numeric_ulong(Type, Frag, Max) |
+%numeric_type_from(Type, unsigned long) |
+%numeric_unsigned_type_asval(Type, unsigned long, Frag, Max) |
+%enddef |
+ |
+ |
+/* Macro for 'double' derived types */ |
+ |
+%define %numeric_double(Type, Frag, Min, Max) |
+%numeric_type_from(Type, double) |
+%numeric_signed_type_asval(Type, double, Frag , Min, Max) |
+%enddef |
+ |
+ |
+/* Macros for missing fragments */ |
+ |
+%define %ensure_fragment(Fragment) |
+%fragment(`Fragment`,"header") { |
+%#error "Swig language implementation must provide the Fragment fragment" |
+} |
+%enddef |
+ |
+%define %ensure_type_fragments(Type) |
+%fragment(SWIG_From_frag(Type),"header") { |
+%#error "Swig language implementation must provide a SWIG_From_frag(Type) fragment" |
+} |
+%fragment(SWIG_AsVal_frag(Type),"header") { |
+%#error "Swig language implementation must provide a SWIG_AsVal_frag(Type) fragment" |
+} |
+%enddef |