diff --git a/Doc/Manual/C.html b/Doc/Manual/C.html index 627278f33..2b30c4389 100644 --- a/Doc/Manual/C.html +++ b/Doc/Manual/C.html @@ -490,6 +490,159 @@ area: 7.068583 +

C Typemaps, a Code Generation Walkthrough

+ +To get a better idea of which typemap is used for which generated code, have a look at the following 'walk through'.
+Let's assume we have the following C++ interface file, we'd like to generate code for: + +

The Interface

+
+%module example
+
+%inline
+%{
+  class SomeClass{};
+  template <typename T> class SomeTemplateClass{};
+  SomeClass someFunction(SomeTemplateClass<int> &someParameter, int simpleInt);
+%}
+
+%template (SomeIntTemplateClass) SomeTemplateClass<int>;
+
+ + +What we would like to generate as a C interface of this function would be something like this: + +
+//proxy header file
+SomeClass *new_SomeClass(void);
+void delete_SomeClass(SomeClass* carg);
+
+SomeIntTemplateClass * new_SomeIntTemplateClass();
+void delete_SomeIntTemplateClass(SomeIntTemplateClass * carg1);
+
+SomeClass *someFunction(SomeIntTemplateClass *someParameter, int simpleInt);
+
+ +When we generate the bindings, we generate code for two translation units: + +We need 2 translation units to be able to have C types with the same names as the original C++ types. + +

The Wrapper

+Since the proxy embeds a call to the wrapper function, we'll examine the generation of the wrapper function first. + +
+SWIGEXPORTC SwigObj * _wrap_someFunction(SwigObj * carg1, int carg2) {
+  SomeClass * cppresult;
+  SomeTemplateClass< int > *arg1 = 0 ;
+  int arg2 ;
+  SwigObj * result;
+  
+  {
+    if (carg1)
+    arg1 = (SomeTemplateClass< int > *) carg1->obj;
+    else
+    arg1 = (SomeTemplateClass< int > *) 0;
+  }
+  arg2 = (int) carg2;
+  {
+    const int &_result_ref =  someFunction(*arg1,arg2);cppresult = (int*) &_result_ref;
+  }
+  {
+    result = (SwigObj*) SWIG_create_object(SWIG_STR(SomeClass));
+    result->obj = (void*) &cppresult;
+  }
+  return result;
+}
+
+ +It might be helpful to think of the way function calls are generated as a composition of building blocks.
+A typical wrapper will be composited with these [optional] blocks: + +
    +
  1. Prototype
  2. +
  3. C return value variable
  4. +
  5. Local variables equal to the called C++ function's parameters
  6. +
  7. [C++ return value variable]
  8. +
  9. Assignment (extraction) of wrapper parameters to local parameter copies
  10. +
  11. [Contract (e.g. constraints) checking]
  12. +
  13. C++ function call
  14. +
  15. [Exception handling]
  16. +
  17. [Assignment to C++ return value]
  18. +
  19. Assignment to C return value
  20. +
+ +Let's go through it step by step and start with the wrapper prototype + +
+couttype                     ctype            ctype
+---------                    ---------        ---
+SwigObj * _wrap_someFunction(SwigObj * carg1, int carg2);
+
+ +As first unit of the wrapper code, a variable to hold the return value of the function is emitted to the wrapper's body + +
+couttype
+---------
+SwigObj * result;
+
+ +Now for each of the C++ function's arguments, a local variable with the very same type is emitted to the wrapper's body. + +
+SomeTemplateClass< int > *arg1 = 0 ;
+int arg2 ;
+
+ +If it's a C++ function that is wrapped (in this case it is), another variable is emitted for the 'original' return value of the C++ function.
+At this point, we simply 'inject' behavior if it's a C++ function that is wrapped (in this cas it obviously is). + +
+cppouttype
+-----------
+SomeClass * cppresult;
+
+ +Next, the values of the input parameters are assigned to the local variables using the 'in' typemap. + +
+{
+  if (carg1)
+  arg1 = (SomeTemplateClass< int > *) carg1->obj;
+  else
+  arg1 = (SomeTemplateClass< int > *) 0;
+}
+arg2 = (int) carg2;
+
+ +A reasonable question would be: "Why aren't the parameters assigned in the declaration of their local counterparts?"
+As seen above, for complex types pointers have to be verified before extracting and
+casting the actual data pointer from the provided SwigObj pointer.
+This could easily become messy if it was done in the same line with the local variable declaration.
+

+At this point we are ready to call the C++ function with our parameters.
+

+
+{
+  const int &_result_ref =  someFunction(*arg1,arg2);cppresult = (int*) &_result_ref;
+}
+
+Subsequently, the return value is assigned to the dedicated return value variable using the 'out' typemap +
+{
+  result = (SwigObj*) SWIG_create_object(SWIG_STR(SomeClass));
+  result->obj = (void*) &cppresult;
+}
+
+ +Finally, the return value variable is returned. +
+return result;
+
+

36.5 Exception handling