Add beginning of 'which typemap is for what' for C backend documentation.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2012-c@13639 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
1c38df4ceb
commit
a826cdda4e
1 changed files with 153 additions and 0 deletions
|
|
@ -490,6 +490,159 @@ area: 7.068583
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<H3>C Typemaps, a Code Generation Walkthrough</H3>
|
||||||
|
|
||||||
|
To get a better idea of which typemap is used for which generated code, have a look at the following 'walk through'.</br>
|
||||||
|
Let's assume we have the following C++ interface file, we'd like to generate code for:
|
||||||
|
|
||||||
|
<H4>The Interface</H4>
|
||||||
|
<div class="code"><pre>
|
||||||
|
%module example
|
||||||
|
|
||||||
|
%inline
|
||||||
|
%{
|
||||||
|
class SomeClass{};
|
||||||
|
template <typename T> class SomeTemplateClass{};
|
||||||
|
SomeClass someFunction(SomeTemplateClass<int> &someParameter, int simpleInt);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template (SomeIntTemplateClass) SomeTemplateClass<int>;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
|
||||||
|
What we would like to generate as a C interface of this function would be something like this:
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
//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);
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
When we generate the bindings, we generate code for two translation units:
|
||||||
|
<ul>
|
||||||
|
<li>The proxy</li>
|
||||||
|
<li>The wrapper</li>
|
||||||
|
</ul>
|
||||||
|
We need 2 translation units to be able to have C types with the same names as the original C++ types.
|
||||||
|
|
||||||
|
<H4>The Wrapper</H4>
|
||||||
|
Since the proxy embeds a call to the wrapper function, we'll examine the generation of the wrapper function first.
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
It might be helpful to think of the way function calls are generated as a composition of building blocks.</br>
|
||||||
|
A typical wrapper will be composited with these [optional] blocks:
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Prototype</li>
|
||||||
|
<li>C return value variable</li>
|
||||||
|
<li>Local variables equal to the called C++ function's parameters</li>
|
||||||
|
<li>[C++ return value variable]</li>
|
||||||
|
<li>Assignment (extraction) of wrapper parameters to local parameter copies</li>
|
||||||
|
<li>[Contract (e.g. constraints) checking]</li>
|
||||||
|
<li> C++ function call</li>
|
||||||
|
<li>[Exception handling]</li>
|
||||||
|
<li>[Assignment to C++ return value]</li>
|
||||||
|
<li>Assignment to C return value</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
Let's go through it step by step and start with the wrapper prototype
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
couttype ctype ctype
|
||||||
|
--------- --------- ---
|
||||||
|
SwigObj * _wrap_someFunction(SwigObj * carg1, int carg2);
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
As first unit of the wrapper code, a variable to hold the return value of the function is emitted to the wrapper's body
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
couttype
|
||||||
|
---------
|
||||||
|
SwigObj * result;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
Now for each of the C++ function's arguments, a local variable with the very same type is emitted to the wrapper's body.
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
SomeTemplateClass< int > *arg1 = 0 ;
|
||||||
|
int arg2 ;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
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.</br>
|
||||||
|
At this point, we simply 'inject' behavior if it's a C++ function that is wrapped (in this cas it obviously is).
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
cppouttype
|
||||||
|
-----------
|
||||||
|
SomeClass * cppresult;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
Next, the values of the input parameters are assigned to the local variables using the 'in' typemap.
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
{
|
||||||
|
if (carg1)
|
||||||
|
arg1 = (SomeTemplateClass< int > *) carg1->obj;
|
||||||
|
else
|
||||||
|
arg1 = (SomeTemplateClass< int > *) 0;
|
||||||
|
}
|
||||||
|
arg2 = (int) carg2;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
A reasonable question would be: "Why aren't the parameters assigned in the declaration of their local counterparts?"</br>
|
||||||
|
As seen above, for complex types pointers have to be verified before extracting and </br>
|
||||||
|
casting the actual data pointer from the provided SwigObj pointer.</br>
|
||||||
|
This could easily become messy if it was done in the same line with the local variable declaration.</br>
|
||||||
|
<p>
|
||||||
|
At this point we are ready to call the C++ function with our parameters.</br>
|
||||||
|
</p>
|
||||||
|
<div class="code"><pre>
|
||||||
|
{
|
||||||
|
const int &_result_ref = someFunction(*arg1,arg2);cppresult = (int*) &_result_ref;
|
||||||
|
}
|
||||||
|
</pre></div>
|
||||||
|
Subsequently, the return value is assigned to the dedicated return value variable using the 'out' typemap
|
||||||
|
<div class="code"><pre>
|
||||||
|
{
|
||||||
|
result = (SwigObj*) SWIG_create_object(SWIG_STR(SomeClass));
|
||||||
|
result->obj = (void*) &cppresult;
|
||||||
|
}
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
Finally, the return value variable is returned.
|
||||||
|
<div class="code"><pre>
|
||||||
|
return result;
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
<H2><a name="C_exceptions"></a>36.5 Exception handling</H2>
|
<H2><a name="C_exceptions"></a>36.5 Exception handling</H2>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue