mirror of https://github.com/swig/swig
3920 lines
105 KiB
HTML
3920 lines
105 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>Typemaps</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="Typemaps"></a>10 Typemaps</H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Typemaps_nn2">Introduction</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn3">Type conversion</a>
|
|
<li><a href="#Typemaps_nn4">Typemaps</a>
|
|
<li><a href="#Typemaps_nn5">Pattern matching</a>
|
|
<li><a href="#Typemaps_nn6">Reusing typemaps</a>
|
|
<li><a href="#Typemaps_nn7">What can be done with typemaps?</a>
|
|
<li><a href="#Typemaps_nn8">What can't be done with typemaps?</a>
|
|
<li><a href="#Typemaps_nn9">The rest of this chapter</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn10">Typemap specifications</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn11">Defining a typemap</a>
|
|
<li><a href="#Typemaps_nn12">Typemap scope</a>
|
|
<li><a href="#Typemaps_nn13">Copying a typemap</a>
|
|
<li><a href="#Typemaps_nn14">Deleting a typemap</a>
|
|
<li><a href="#Typemaps_nn15">Placement of typemaps</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn16">Pattern matching rules</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn17">Basic matching rules</a>
|
|
<li><a href="#Typemaps_nn18">Typedef reductions</a>
|
|
<li><a href="#Typemaps_nn19">Default typemaps</a>
|
|
<li><a href="#Typemaps_mixed_default">Mixed default typemaps</a>
|
|
<li><a href="#Typemaps_nn20">Multi-arguments typemaps</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn21">Code generation rules</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn22">Scope</a>
|
|
<li><a href="#Typemaps_nn23">Declaring new local variables</a>
|
|
<li><a href="#Typemaps_special_variables">Special variables</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn25">Common typemap methods</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn26">"in" typemap</a>
|
|
<li><a href="#Typemaps_nn27">"typecheck" typemap</a>
|
|
<li><a href="#Typemaps_nn28">"out" typemap</a>
|
|
<li><a href="#Typemaps_nn29">"arginit" typemap</a>
|
|
<li><a href="#Typemaps_nn30">"default" typemap</a>
|
|
<li><a href="#Typemaps_nn31">"check" typemap</a>
|
|
<li><a href="#Typemaps_nn32">"argout" typemap</a>
|
|
<li><a href="#Typemaps_nn33">"freearg" typemap</a>
|
|
<li><a href="#Typemaps_nn34">"newfree" typemap</a>
|
|
<li><a href="#Typemaps_nn35">"memberin" typemap</a>
|
|
<li><a href="#Typemaps_nn36">"varin" typemap</a>
|
|
<li><a href="#Typemaps_nn37">"varout" typemap</a>
|
|
<li><a href="#throws_typemap">"throws" typemap</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn39">Some typemap examples</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn40">Typemaps for arrays</a>
|
|
<li><a href="#Typemaps_nn41">Implementing constraints with typemaps</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_nn43">Typemaps for multiple languages</a>
|
|
<li><a href="#Typemaps_optimal">Optimal code generation when returning by value</a>
|
|
<li><a href="#Typemaps_multi_argument_typemaps">Multi-argument typemaps</a>
|
|
<li><a href="#runtime_type_checker">The run-time type checker</a>
|
|
<ul>
|
|
<li><a href="#Typemaps_nn45">Implementation</a>
|
|
<li><a href="#Typemaps_nn46">Usage</a>
|
|
</ul>
|
|
<li><a href="#Typemaps_overloading">Typemaps and overloading</a>
|
|
<li><a href="#Typemaps_nn48">More about <tt>%apply</tt> and <tt>%clear</tt></a>
|
|
<li><a href="#Typemaps_nn49">Reducing wrapper code size</a>
|
|
<li><a href="#Typemaps_nn47">Passing data between typemaps</a>
|
|
<li><a href="#Typemaps_nn51">Where to go for more information?</a>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
<b>Disclaimer: This chapter is under construction!</b>
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_nn2"></a>10.1 Introduction</H2>
|
|
|
|
|
|
<p>
|
|
Chances are, you are reading this chapter for one of two reasons; you
|
|
either want to customize SWIG's behavior or you overheard someone
|
|
mumbling some incomprehensible drivel about "typemaps" and you asked
|
|
yourself "typemaps, what are those?" That said, let's start with a
|
|
short disclaimer that "typemaps" are an advanced customization feature
|
|
that provide direct access to SWIG's low-level code generator. Not
|
|
only that, they are an integral part of the SWIG C++ type system (a
|
|
non-trivial topic of its own). Typemaps are generally
|
|
<em>not</em> a required part of using SWIG. Therefore, you might want
|
|
to re-read the earlier chapters if you have found your way to this
|
|
chapter with only a vague idea of what SWIG already does by default.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn3"></a>10.1.1 Type conversion</H3>
|
|
|
|
|
|
<p>
|
|
One of the most important problems in wrapper code generation is the
|
|
conversion of datatypes between programming languages. Specifically,
|
|
for every C/C++ declaration, SWIG must somehow generate wrapper code
|
|
that allows values to be passed back and forth between languages.
|
|
Since every programming language represents data differently, this is
|
|
not a simple of matter of simply linking code together with the
|
|
C linker. Instead, SWIG has to know something about how data is
|
|
represented in each language and how it can be manipulated.
|
|
</p>
|
|
|
|
<p>
|
|
To illustrate, suppose you had a simple C function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int factorial(int n);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To access this function from Python, a pair of Python API functions
|
|
are used to convert integer values. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
long PyInt_AsLong(PyObject *obj); /* Python --> C */
|
|
PyObject *PyInt_FromLong(long x); /* C --> Python */
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The first function is used to convert the input argument from a Python integer object
|
|
to C <tt>long</tt>. The second function is used to convert a value from C back into a Python integer object.
|
|
</p>
|
|
|
|
<p>
|
|
Inside the wrapper function, you might see these functions used like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
PyObject *wrap_factorial(PyObject *self, PyObject *args) {
|
|
int arg1;
|
|
int result;
|
|
PyObject *obj1;
|
|
PyObject *resultobj;
|
|
|
|
if (!PyArg_ParseTuple("O:factorial", &obj1)) return NULL;
|
|
<b>arg1 = PyInt_AsLong(obj1);</b>
|
|
result = factorial(arg1);
|
|
<b>resultobj = PyInt_FromLong(result);</b>
|
|
return resultobj;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Every target language supported by SWIG has functions that work in a similar manner. For example, in
|
|
Perl, the following functions are used:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
IV SvIV(SV *sv); /* Perl --> C */
|
|
void sv_setiv(SV *sv, IV val); /* C --> Perl */
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In Tcl:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *obj, long *value);
|
|
Tcl_Obj *Tcl_NewIntObj(long value);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The precise details are not so important. What is important is that
|
|
all of the underlying type conversion is handled by collections of
|
|
utility functions and short bits of C code like this---you simply have
|
|
to read the extension documentation for your favorite language to know
|
|
how it works (an exercise left to the reader).
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn4"></a>10.1.2 Typemaps</H3>
|
|
|
|
|
|
<p>
|
|
Since type handling is so central to wrapper code generation, SWIG
|
|
allows it to be completely defined (or redefined) by the user. To do this,
|
|
a special <tt>%typemap</tt> directive is used. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Convert from Python --> C */
|
|
%typemap(in) int {
|
|
$1 = PyInt_AsLong($input);
|
|
}
|
|
|
|
/* Convert from C --> Python */
|
|
%typemap(out) int {
|
|
$result = PyInt_FromLong($1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
At first glance, this code will look a little confusing.
|
|
However, there is really not much to it. The first typemap (the "in"
|
|
typemap) is used to convert a value from the target language to C. The second
|
|
typemap (the "out" typemap) is used to convert in the other
|
|
direction. The content of each typemap is a small fragment of C code
|
|
that is inserted directly into the SWIG generated wrapper functions. Within
|
|
this code, a number of special variables prefixed with a $ are expanded. These are
|
|
really just placeholders for C variables that are generated in the course
|
|
of creating the wrapper function. In this case, <tt>$input</tt> refers to an
|
|
input object that needs to be converted to C and <tt>$result</tt>
|
|
refers to an object that is going to be returned by a wrapper
|
|
function. <tt>$1</tt> refers to a C variable that has the same type as
|
|
specified in the typemap declaration (an <tt>int</tt> in this
|
|
example).
|
|
</p>
|
|
|
|
<p>
|
|
A short example might make this a little more clear. If you were wrapping a
|
|
function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int gcd(int x, int y);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A wrapper function would look approximately like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
PyObject *wrap_gcd(PyObject *self, PyObject *args) {
|
|
int arg1;
|
|
int arg2;
|
|
int result;
|
|
PyObject *obj1;
|
|
PyObject *obj2;
|
|
PyObject *resultobj;
|
|
|
|
if (!PyArg_ParseTuple("OO:gcd", &obj1, &obj2)) return NULL;
|
|
|
|
/* "in" typemap, argument 1 */<b>
|
|
{
|
|
arg1 = PyInt_AsLong(obj1);
|
|
}
|
|
</b>
|
|
/* "in" typemap, argument 2 */<b>
|
|
{
|
|
arg2 = PyInt_AsLong(obj2);
|
|
}
|
|
</b>
|
|
result = gcd(arg1,arg2);
|
|
|
|
/* "out" typemap, return value */<b>
|
|
{
|
|
resultobj = PyInt_FromLong(result);
|
|
}
|
|
</b>
|
|
return resultobj;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this code, you can see how the typemap code has been inserted into
|
|
the function. You can also see how the special $ variables have been
|
|
expanded to match certain variable names inside the wrapper function. This is really the
|
|
whole idea behind typemaps--they simply let you insert arbitrary code into different
|
|
parts of the generated wrapper functions. Because arbitrary code can be inserted, it
|
|
possible to completely change the way in which values are converted.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn5"></a>10.1.3 Pattern matching</H3>
|
|
|
|
|
|
<p>
|
|
As the name implies, the purpose of a typemap is to "map" C datatypes to
|
|
types in the target language. Once a typemap is defined for a C datatype,
|
|
it is applied to all future occurrences of that type in the input file. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Convert from Perl --> C */
|
|
%typemap(in) <b>int</b> {
|
|
$1 = SvIV($input);
|
|
}
|
|
|
|
...
|
|
int factorial(<b>int</b> n);
|
|
int gcd(<b>int</b> x, <b>int</b> y);
|
|
int count(char *s, char *t, <b>int</b> max);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The matching of typemaps to C datatypes is more than a simple textual match. In fact,
|
|
typemaps are fully built into the underlying type system. Therefore, typemaps are
|
|
unaffected by <tt>typedef</tt>, namespaces, and other declarations that might hide the
|
|
underlying type. For example, you could have code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Convert from Ruby--> C */
|
|
%typemap(in) <b>int</b> {
|
|
$1 = NUM2INT($input);
|
|
}
|
|
...
|
|
typedef int Integer;
|
|
namespace foo {
|
|
typedef Integer Number;
|
|
};
|
|
|
|
int foo(<b>int</b> x);
|
|
int bar(<b>Integer</b> y);
|
|
int spam(<b>foo::Number</b> a, <b>foo::Number</b> b);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, the typemap is still applied to the proper arguments even though typenames don't always
|
|
match the text "int". This ability to track types is a critical part of SWIG--in fact, all
|
|
of the target language modules work merely define a set of typemaps for the basic types. Yet, it
|
|
is never necessary to write new typemaps for typenames introduced by <tt>typedef</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
In addition to tracking typenames, typemaps may also be specialized to match against a specific argument name. For
|
|
example, you could write a typemap like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) <b>double nonnegative</b> {
|
|
$1 = PyFloat_AsDouble($input);
|
|
if ($1 < 0) {
|
|
PyErr_SetString(PyExc_ValueError,"argument must be nonnegative.");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
...
|
|
double sin(double x);
|
|
double cos(double x);
|
|
double sqrt(<b>double nonnegative</b>);
|
|
|
|
typedef double Real;
|
|
double log(<b>Real nonnegative</b>);
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For certain tasks such as input argument conversion, typemaps can be defined for sequences of
|
|
consecutive arguments. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (<b>char *str, int len</b>) {
|
|
$1 = PyString_AsString($input); /* char *str */
|
|
$2 = PyString_Size($input); /* int len */
|
|
}
|
|
...
|
|
int count(<b>char *str, int len</b>, char c);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, a single input object is expanded into a pair of C arguments. This example also
|
|
provides a hint to the unusual variable naming scheme involving <tt>$1</tt>, <tt>$2</tt>, and so forth.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn6"></a>10.1.4 Reusing typemaps</H3>
|
|
|
|
|
|
<p>
|
|
Typemaps are normally defined for specific type and argument name patterns. However, typemaps can also
|
|
be copied and reused. One way to do this is to use assignment like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) Integer = int;
|
|
%typemap(in) (char *buffer, int size) = (char *str, int len);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A more general form of copying is found in the <tt>%apply</tt> directive like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int {
|
|
/* Convert an integer argument */
|
|
...
|
|
}
|
|
%typemap(out) int {
|
|
/* Return an integer value */
|
|
...
|
|
}
|
|
|
|
/* Apply all of the integer typemaps to size_t */
|
|
%apply int { size_t };
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<tt>%apply</tt> merely takes <em>all</em> of the typemaps that are defined for one type and
|
|
applies them to other types. Note: you can include a comma separated set of types in the
|
|
<tt>{ ... }</tt> part of <tt>%apply</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
It should be noted that it is not necessary to copy typemaps for types that are related by <tt>typedef</tt>.
|
|
For example, if you have this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
typedef int size_t;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then SWIG already knows that the <tt>int</tt> typemaps apply. You don't have to do anything.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn7"></a>10.1.5 What can be done with typemaps?</H3>
|
|
|
|
|
|
<p>
|
|
The primary use of typemaps is for defining wrapper generation behavior at the level
|
|
of individual C/C++ datatypes. There are currently six general categories of problems that
|
|
typemaps address:
|
|
</p>
|
|
|
|
<p>
|
|
<b>Argument handling</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int foo(<b>int x, double y, char *s</b>);
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Input argument conversion ("in" typemap).</li>
|
|
<li>Input argument type checking ("typecheck" typemap).</li>
|
|
<li>Output argument handling ("argout" typemap).</li>
|
|
<li>Input argument value checking ("check" typemap).</li>
|
|
<li>Input argument initialization ("arginit" typemap).</li>
|
|
<li>Default arguments ("default" typemap).</li>
|
|
<li>Input argument resource management ("freearg" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
<b>Return value handling</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
<b>int</b> foo(int x, double y, char *s);
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Function return value conversion ("out" typemap).</li>
|
|
<li>Return value resource management ("ret" typemap).</li>
|
|
<li>Resource management for newly allocated objects ("newfree" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
<b>Exception handling</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
<b>int</b> foo(int x, double y, char *s) throw(<b>MemoryError, IndexError</b>);
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Handling of C++ exception specifications. ("throw" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
<b>Global variables</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
<b>int foo;</b>
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Assignment of a global variable. ("varin" typemap).</li>
|
|
<li>Reading a global variable. ("varout" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
<b>Member variables</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
struct Foo {
|
|
<b>int x[20]</b>;
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Assignment of data to a class/structure member. ("memberin" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
<b>Constant creation</b>
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
#define FOO 3
|
|
%constant int BAR = 42;
|
|
enum { ALE, LAGER, STOUT };
|
|
</pre>
|
|
</div>
|
|
|
|
<ul>
|
|
<li>Creation of constant values. ("consttab" or "constcode" typemap).</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Details of each of these typemaps will be covered shortly. Also, certain language modules may define additional
|
|
typemaps that expand upon this list. For example, the Java module defines a variety of typemaps for controlling additional
|
|
aspects of the Java bindings. Consult language specific documentation for further details.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn8"></a>10.1.6 What can't be done with typemaps?</H3>
|
|
|
|
|
|
<p>
|
|
Typemaps can't be used to define properties that apply to C/C++ declarations as a whole. For example,
|
|
suppose you had a declaration like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Foo *make_Foo();
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
and you wanted to tell SWIG that <tt>make_Foo()</tt> returned a newly
|
|
allocated object (for the purposes of providing better memory
|
|
management). Clearly, this property of <tt>make_Foo()</tt> is
|
|
<em>not</em> a property that would be associated with the datatype
|
|
<tt>Foo *</tt> by itself. Therefore, a completely different SWIG
|
|
customization mechanism (<tt>%feature</tt>) is used for this purpose. Consult the <a
|
|
href="Customization.html#Customization">Customization Features</a> chapter for more
|
|
information about that.
|
|
</p>
|
|
|
|
<p>
|
|
Typemaps also can't be used to rearrange or transform the order of arguments. For example,
|
|
if you had a function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void foo(int, char *);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
you can't use typemaps to interchange the arguments, allowing you to call the
|
|
function like this:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
foo("hello",3) # Reversed arguments
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you want to change the calling conventions of a function, write a helper
|
|
function instead. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%rename(foo) wrap_foo;
|
|
%inline %{
|
|
void wrap_foo(char *s, int x) {
|
|
foo(x,s);
|
|
}
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn9"></a>10.1.7 The rest of this chapter</H3>
|
|
|
|
|
|
<p>
|
|
The rest of this chapter provides detailed information for people who
|
|
want to write new typemaps. This information is of particular importance to anyone
|
|
who intends to write a new SWIG target language module. Power users can also
|
|
use this information to write application specific type conversion rules.
|
|
</p>
|
|
|
|
<p>
|
|
Since typemaps are strongly tied to the underlying C++ type system,
|
|
subsequent sections assume that you are reasonably familiar with the
|
|
basic details of values, pointers, references, arrays, type qualifiers
|
|
(e.g., <tt>const</tt>), structures, namespaces, templates, and memory
|
|
management in C/C++. If not, you would be well-advised to consult a copy
|
|
of "The C Programming Language" by Kernighan and Ritchie or
|
|
"The C++ Programming Language" by Stroustrup before going any further.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_nn10"></a>10.2 Typemap specifications</H2>
|
|
|
|
|
|
<p>
|
|
This section describes the behavior of the <tt>%typemap</tt> directive itself.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn11"></a>10.2.1 Defining a typemap</H3>
|
|
|
|
|
|
<p>
|
|
New typemaps are defined using the <tt>%typemap</tt> declaration. The general form of
|
|
this declaration is as follows (parts enclosed in [ ... ] are optional):
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(<em>method</em> [, <em>modifiers</em>]) <em>typelist</em> <em>code</em> ;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<em>method</em> is a simply a name that specifies what kind of typemap is being defined. It
|
|
is usually a name like <tt>"in"</tt>, <tt>"out"</tt>, or <tt>"argout"</tt>. The purpose of
|
|
these methods is described later.
|
|
</p>
|
|
|
|
<p>
|
|
<em>modifiers</em> is an optional comma separated list of <tt>name="value"</tt> values. These
|
|
are sometimes to attach extra information to a typemap and is often target-language dependent.
|
|
</p>
|
|
|
|
<p>
|
|
<em>typelist</em> is a list of the C++ type patterns that the typemap will match. The general form of
|
|
this list is as follows:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
typelist : typepattern [, typepattern, typepattern, ... ] ;
|
|
|
|
typepattern : type [ (parms) ]
|
|
| type name [ (parms) ]
|
|
| ( typelist ) [ (parms) ]
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Each type pattern is either a simple type, a simple type and argument name, or a list of types in the
|
|
case of multi-argument typemaps. In addition, each type pattern can be parameterized with a list of temporary
|
|
variables (parms). The purpose of these variables will be explained shortly.
|
|
</p>
|
|
|
|
<p><em>code</em> specifies the code used in the typemap.
|
|
Usually this is C/C++ code, but in the statically typed target languages, such as Java and C#, this can contain target language code for certain typemaps.
|
|
It can take any one of the following forms:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
code : { ... }
|
|
| " ... "
|
|
| %{ ... %}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note that the preprocessor will expand code within the {} delimiters, but not in the last two styles of delimiters,
|
|
see <a href="Preprocessor.html#Preprocessor_typemap_delimiters">Preprocessor and Typemaps</a>.
|
|
Here are some examples of valid typemap specifications:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Simple typemap declarations */
|
|
%typemap(in) int {
|
|
$1 = PyInt_AsLong($input);
|
|
}
|
|
%typemap(in) int "$1 = PyInt_AsLong($input);";
|
|
%typemap(in) int %{
|
|
$1 = PyInt_AsLong($input);
|
|
%}
|
|
|
|
/* Typemap with extra argument name */
|
|
%typemap(in) int nonnegative {
|
|
...
|
|
}
|
|
|
|
/* Multiple types in one typemap */
|
|
%typemap(in) int, short, long {
|
|
$1 = SvIV($input);
|
|
}
|
|
|
|
/* Typemap with modifiers */
|
|
%typemap(in,doc="integer") int "$1 = gh_scm2int($input);";
|
|
|
|
/* Typemap applied to patterns of multiple arguments */
|
|
%typemap(in) (char *str, int len),
|
|
(char *buffer, int size)
|
|
{
|
|
$1 = PyString_AsString($input);
|
|
$2 = PyString_Size($input);
|
|
}
|
|
|
|
/* Typemap with extra pattern parameters */
|
|
%typemap(in, numinputs=0) int *output (int temp),
|
|
long *output (long temp)
|
|
{
|
|
$1 = &temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Admittedly, it's not the most readable syntax at first glance. However, the purpose of the
|
|
individual pieces will become clear.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn12"></a>10.2.2 Typemap scope</H3>
|
|
|
|
|
|
<p>
|
|
Once defined, a typemap remains in effect for all of the declarations that follow. A typemap may be redefined for
|
|
different sections of an input file. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// typemap1
|
|
%typemap(in) int {
|
|
...
|
|
}
|
|
|
|
int fact(int); // typemap1
|
|
int gcd(int x, int y); // typemap1
|
|
|
|
// typemap2
|
|
%typemap(in) int {
|
|
...
|
|
}
|
|
|
|
int isprime(int); // typemap2
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
One exception to the typemap scoping rules pertains to the <tt>%extend</tt> declaration. <tt>%extend</tt> is used to attach
|
|
new declarations to a class or structure definition. Because of this, all of the declarations in an <tt>%extend</tt> block are
|
|
subject to the typemap rules that are in effect at the point where the class itself is defined. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
...
|
|
};
|
|
|
|
%typemap(in) int {
|
|
...
|
|
}
|
|
|
|
%extend Foo {
|
|
int blah(int x); // typemap has no effect. Declaration is attached to Foo which
|
|
// appears before the %typemap declaration.
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn13"></a>10.2.3 Copying a typemap</H3>
|
|
|
|
|
|
<p>
|
|
A typemap is copied by using assignment. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) Integer = int;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
or this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) Integer, Number, int32_t = int;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Types are often managed by a collection of different typemaps. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int { ... }
|
|
%typemap(out) int { ... }
|
|
%typemap(varin) int { ... }
|
|
%typemap(varout) int { ... }
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To copy all of these typemaps to a new type, use <tt>%apply</tt>. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%apply int { Integer }; // Copy all int typemaps to Integer
|
|
%apply int { Integer, Number }; // Copy all int typemaps to both Integer and Number
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The patterns for <tt>%apply</tt> follow the same rules as for <tt>%typemap</tt>. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%apply int *output { Integer *output }; // Typemap with name
|
|
%apply (char *buf, int len) { (char *buffer, int size) }; // Multiple arguments
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn14"></a>10.2.4 Deleting a typemap</H3>
|
|
|
|
|
|
<p>
|
|
A typemap can be deleted by simply defining no code. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int; // Clears typemap for int
|
|
%typemap(in) int, long, short; // Clears typemap for int, long, short
|
|
%typemap(in) int *output;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The <tt>%clear</tt> directive clears all typemaps for a given type.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%clear int; // Removes all types for int
|
|
%clear int *output, long *output;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Note:</b> Since SWIG's default behavior is defined by typemaps, clearing a fundamental type like
|
|
<tt>int</tt> will make that type unusable unless you also define a new set of typemaps immediately
|
|
after the clear operation.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn15"></a>10.2.5 Placement of typemaps</H3>
|
|
|
|
|
|
<p>
|
|
Typemap declarations can be declared in the global scope, within a C++ namespace, and within a C++ class. For
|
|
example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int {
|
|
...
|
|
}
|
|
|
|
namespace std {
|
|
class string;
|
|
%typemap(in) string {
|
|
...
|
|
}
|
|
}
|
|
|
|
class Bar {
|
|
public:
|
|
typedef const int & const_reference;
|
|
%typemap(out) const_reference {
|
|
...
|
|
}
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When a typemap appears inside a namespace or class, it stays in effect until the end of the SWIG input
|
|
(just like before). However, the typemap takes the local scope into account. Therefore, this
|
|
code
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
namespace std {
|
|
class string;
|
|
%typemap(in) string {
|
|
...
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
is really defining a typemap for the type <tt>std::string</tt>. You could have code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
namespace std {
|
|
class string;
|
|
%typemap(in) string { /* std::string */
|
|
...
|
|
}
|
|
}
|
|
|
|
namespace Foo {
|
|
class string;
|
|
%typemap(in) string { /* Foo::string */
|
|
...
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, there are two completely distinct typemaps that apply to two completely different
|
|
types (<tt>std::string</tt> and <tt>Foo::string</tt>).
|
|
</p>
|
|
|
|
<p>
|
|
It should be noted that for scoping to work, SWIG has to know that <tt>string</tt> is a typename defined
|
|
within a particular namespace. In this example, this is done using the class declaration <tt>class string</tt>.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_nn16"></a>10.3 Pattern matching rules</H2>
|
|
|
|
|
|
<p>
|
|
The section describes the pattern matching rules by which C datatypes are associated with typemaps.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn17"></a>10.3.1 Basic matching rules</H3>
|
|
|
|
|
|
<p>
|
|
Typemaps are matched using both a type and a name (typically the name of a argument). For a given
|
|
<tt>TYPE NAME</tt> pair, the following rules are applied, in order, to find a match. The first typemap found
|
|
is used.
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Typemaps that exactly match <tt>TYPE</tt> and <tt>NAME</tt>.
|
|
<li>Typemaps that exactly match <tt>TYPE</tt> only.
|
|
</ul>
|
|
|
|
<p>
|
|
If <tt>TYPE</tt> includes qualifiers (const, volatile, etc.), they are stripped and the following
|
|
checks are made:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Typemaps that match the stripped <tt>TYPE</tt> and <tt>NAME</tt>.
|
|
<Li>Typemaps that match the stripped <tt>TYPE</tt> only.
|
|
</ul>
|
|
|
|
<p>
|
|
If <tt>TYPE</tt> is an array. The following transformation is made:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Replace all dimensions to <tt>[ANY]</tt> and look for a generic array typemap.
|
|
</ul>
|
|
|
|
<p>
|
|
To illustrate, suppose that you had a function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int foo(const char *s);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To find a typemap for the argument <tt>const char *s</tt>, SWIG will search for the following typemaps:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
const char *s Exact type and name match
|
|
const char * Exact type match
|
|
char *s Type and name match (stripped qualifiers)
|
|
char * Type match (stripped qualifiers)
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When more than one typemap rule might be defined, only the first match
|
|
found is actually used. Here is an example that
|
|
shows how some of the basic rules are applied:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%typemap(in) int *x {
|
|
... typemap 1
|
|
}
|
|
|
|
%typemap(in) int * {
|
|
... typemap 2
|
|
}
|
|
|
|
%typemap(in) const int *z {
|
|
... typemap 3
|
|
}
|
|
|
|
%typemap(in) int [4] {
|
|
... typemap 4
|
|
}
|
|
|
|
%typemap(in) int [ANY] {
|
|
... typemap 5
|
|
}
|
|
|
|
void A(int *x); // int *x rule (typemap 1)
|
|
void B(int *y); // int * rule (typemap 2)
|
|
void C(const int *x); // int *x rule (typemap 1)
|
|
void D(const int *z); // int * rule (typemap 3)
|
|
void E(int x[4]); // int [4] rule (typemap 4)
|
|
void F(int x[1000]); // int [ANY] rule (typemap 5)
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn18"></a>10.3.2 Typedef reductions</H3>
|
|
|
|
|
|
<p>
|
|
If no match is found using the rules in the previous section, SWIG
|
|
applies a typedef reduction to the type and repeats the typemap search
|
|
for the reduced type. To illustrate, suppose you had code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int {
|
|
... typemap 1
|
|
}
|
|
|
|
typedef int Integer;
|
|
void blah(Integer x);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To find the typemap for <tt>Integer x</tt>, SWIG will first search for the following
|
|
typemaps:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
Integer x
|
|
Integer
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Finding no match, it then applies a reduction <tt>Integer -> int</tt> to the type and
|
|
repeats the search.
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
int x
|
|
int --> match: typemap 1
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Even though two types might be the same via typedef, SWIG allows typemaps to be defined
|
|
for each typename independently. This allows for interesting customization possibilities based
|
|
solely on the typename itself. For example, you could write code like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
typedef double pdouble; // Positive double
|
|
|
|
// typemap 1
|
|
%typemap(in) double {
|
|
... get a double ...
|
|
}
|
|
// typemap 2
|
|
%typemap(in) pdouble {
|
|
... get a positive double ...
|
|
}
|
|
double sin(double x); // typemap 1
|
|
pdouble sqrt(pdouble x); // typemap 2
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When reducing the type, only one typedef reduction is applied at a
|
|
time. The search process continues to apply reductions until a
|
|
match is found or until no more reductions can be made.
|
|
</p>
|
|
|
|
<p>
|
|
For complicated types, the reduction process can generate a long list of patterns. Consider the following:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
typedef int Integer;
|
|
typedef Integer Row4[4];
|
|
void foo(Row4 rows[10]);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To find a match for the <tt>Row4 rows[10]</tt> argument, SWIG would
|
|
check the following patterns, stopping only when it found a match:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
Row4 rows[10]
|
|
Row4 [10]
|
|
Row4 rows[ANY]
|
|
Row4 [ANY]
|
|
|
|
# Reduce Row4 --> Integer[4]
|
|
Integer rows[10][4]
|
|
Integer [10][4]
|
|
Integer rows[ANY][ANY]
|
|
Integer [ANY][ANY]
|
|
|
|
# Reduce Integer --> int
|
|
int rows[10][4]
|
|
int [10][4]
|
|
int rows[ANY][ANY]
|
|
int [ANY][ANY]
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For parameterized types like templates, the situation is even more complicated. Suppose you had some declarations
|
|
like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
typedef int Integer;
|
|
typedef foo<Integer,Integer> fooii;
|
|
void blah(fooii *x);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, the following typemap patterns are searched for the argument <tt>fooii *x</tt>:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
fooii *x
|
|
fooii *
|
|
|
|
# Reduce fooii --> foo<Integer,Integer>
|
|
foo<Integer,Integer> *x
|
|
foo<Integer,Integer> *
|
|
|
|
# Reduce Integer -> int
|
|
foo<int, Integer> *x
|
|
foo<int, Integer> *
|
|
|
|
# Reduce Integer -> int
|
|
foo<int, int> *x
|
|
foo<int, int> *
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Typemap reductions are always applied to the left-most type that appears. Only when no reductions can be made to the left-most
|
|
type are reductions made to other parts of the type. This behavior means that you could define a typemap for
|
|
<tt>foo<int,Integer></tt>, but a typemap for <tt>foo<Integer,int></tt> would never be matched. Admittedly, this
|
|
is rather esoteric--there's little practical reason to write a typemap quite like that. Of course, you could rely on this
|
|
to confuse your coworkers even more.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn19"></a>10.3.3 Default typemaps</H3>
|
|
|
|
|
|
<p>
|
|
Most SWIG language modules use typemaps to define the default behavior of the C primitive types. This
|
|
is entirely straightforward. For example, a set of typemaps are written like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int "convert an int";
|
|
%typemap(in) short "convert a short";
|
|
%typemap(in) float "convert a float";
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Since typemap matching follows all <tt>typedef</tt> declarations, any sort of type that is
|
|
mapped to a primitive type through <tt>typedef</tt> will be picked up by one of these primitive typemaps.
|
|
</p>
|
|
|
|
<p>
|
|
The default behavior for pointers, arrays, references, and other kinds of types are handled by
|
|
specifying rules for variations of the reserved <tt>SWIGTYPE</tt> type. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) SWIGTYPE * { ... default pointer handling ... }
|
|
%typemap(in) SWIGTYPE & { ... default reference handling ... }
|
|
%typemap(in) SWIGTYPE [] { ... default array handling ... }
|
|
%typemap(in) enum SWIGTYPE { ... default handling for enum values ... }
|
|
%typemap(in) SWIGTYPE (CLASS::*) { ... default pointer member handling ... }
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
These rules match any kind of pointer, reference, or array--even when
|
|
multiple levels of indirection or multiple array dimensions are used.
|
|
Therefore, if you wanted to change SWIG's default handling for all
|
|
types of pointers, you would simply redefine the rule for <tt>SWIGTYPE
|
|
*</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
Finally, the following typemap rule is used to match against simple types that don't match any other rules:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) SWIGTYPE { ... handle an unknown type ... }
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This typemap is important because it is the rule that gets triggered
|
|
when call or return by value is used. For instance, if you have a
|
|
declaration like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
double dot_product(Vector a, Vector b);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The <tt>Vector</tt> type will usually just get matched against
|
|
<tt>SWIGTYPE</tt>. The default implementation of <tt>SWIGTYPE</tt> is
|
|
to convert the value into pointers (as described in chapter 3).
|
|
</p>
|
|
|
|
<p>
|
|
By redefining <tt>SWIGTYPE</tt> it may be possible to implement other
|
|
behavior. For example, if you cleared all typemaps for
|
|
<tt>SWIGTYPE</tt>, SWIG simply won't wrap any unknown datatype (which might
|
|
be useful for debugging). Alternatively, you might modify SWIGTYPE to marshal
|
|
objects into strings instead of converting them to pointers.
|
|
</p>
|
|
|
|
<p>
|
|
The best way to explore the default typemaps is to look at the ones
|
|
already defined for a particular language module. Typemaps
|
|
definitions are usually found in the SWIG library in a file such as
|
|
<tt>python.swg</tt>, <tt>tcl8.swg</tt>, etc.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_mixed_default"></a>10.3.4 Mixed default typemaps</H3>
|
|
|
|
|
|
<p>
|
|
The default typemaps described above can be mixed with <tt>const</tt> and with each other.
|
|
For example the <tt>SWIGTYPE *</tt> typemap is for default pointer handling, but if a <tt>const SWIGTYPE *</tt> typemap
|
|
is defined it will be used instead for constant pointers. Some further examples follow:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) enum SWIGTYPE & { ... enum references ... }
|
|
%typemap(in) const enum SWIGTYPE & { ... const enum references ... }
|
|
%typemap(in) SWIGTYPE *& { ... pointers passed by reference ... }
|
|
%typemap(in) SWIGTYPE * const & { ... constant pointers passed by reference ... }
|
|
%typemap(in) SWIGTYPE[ANY][ANY] { ... 2D arrays ... }
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note that the the typedef reduction described earlier is also used with these mixed default typemaps.
|
|
For example, say the following typemaps are defined and SWIG is looking for the best match for the enum shown below:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) const Hello & { ... }
|
|
%typemap(in) const enum SWIGTYPE & { ... }
|
|
%typemap(in) enum SWIGTYPE & { ... }
|
|
%typemap(in) SWIGTYPE & { ... }
|
|
%typemap(in) SWIGTYPE { ... }
|
|
|
|
enum Hello {};
|
|
const Hello &hi;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The typemap at the top of the list will be chosen, not because it is defined first, but because it is the closest match for the type being wrapped.
|
|
If any of the typemaps in the above list were not defined, then the next one on the list would have precedence.
|
|
In other words the typemap chosen is the closest explicit match.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Compatibility note: </b> The mixed default typemaps were introduced in SWIG-1.3.23, but were not used much in this version.
|
|
Expect to see them being used more and more within the various libraries in later versions of SWIG.
|
|
</p>
|
|
|
|
|
|
<H3><a name="Typemaps_nn20"></a>10.3.5 Multi-arguments typemaps</H3>
|
|
|
|
|
|
<p>
|
|
When multi-argument typemaps are specified, they take precedence over
|
|
any typemaps specified for a single type. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (char *buffer, int len) {
|
|
// typemap 1
|
|
}
|
|
|
|
%typemap(in) char *buffer {
|
|
// typemap 2
|
|
}
|
|
|
|
void foo(char *buffer, int len, int count); // (char *buffer, int len)
|
|
void bar(char *buffer, int blah); // char *buffer
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Multi-argument typemaps are also more restrictive in the way that they are matched.
|
|
Currently, the first argument follows the matching rules described in the previous section,
|
|
but all subsequent arguments must match exactly.
|
|
</p>
|
|
|
|
|
|
<H2><a name="Typemaps_nn21"></a>10.4 Code generation rules</H2>
|
|
|
|
|
|
<p>
|
|
This section describes rules by which typemap code is inserted into
|
|
the generated wrapper code.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn22"></a>10.4.1 Scope</H3>
|
|
|
|
|
|
<p>
|
|
When a typemap is defined like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int {
|
|
$1 = PyInt_AsLong($input);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
the typemap code is inserted into the wrapper function using a new block scope. In other words, the
|
|
wrapper code will look like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
wrap_whatever() {
|
|
...
|
|
// Typemap code
|
|
{
|
|
arg1 = PyInt_AsLong(obj1);
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Because the typemap code is enclosed in its own block, it is legal to declare temporary variables
|
|
for use during typemap execution. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) short {
|
|
long temp; /* Temporary value */
|
|
if (Tcl_GetLongFromObj(interp, $input, &temp) != TCL_OK) {
|
|
return TCL_ERROR;
|
|
}
|
|
$1 = (short) temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Of course, any variables that you declare inside a typemap are destroyed as soon as the typemap
|
|
code has executed (they are not visible to other parts of the wrapper function or other typemaps
|
|
that might use the same variable names).
|
|
</p>
|
|
|
|
<p>
|
|
Occasionally, typemap code will be specified using a few alternative forms. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int "$1 = PyInt_AsLong($input);";
|
|
%typemap(in) int %{
|
|
$1 = PyInt_AsLong($input);
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
These two forms are mainly used for cosmetics--the specified code is not enclosed inside
|
|
a block scope when it is emitted. This sometimes results in a less complicated looking wrapper function.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn23"></a>10.4.2 Declaring new local variables</H3>
|
|
|
|
|
|
<p>
|
|
Sometimes it is useful to declare a new local variable that exists
|
|
within the scope of the entire wrapper function. A good example of this
|
|
might be an application in which you wanted to marshal strings. Suppose
|
|
you had a C++ function like this
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int foo(std::string *s);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
and you wanted to pass a native string in the target language as an argument. For instance,
|
|
in Perl, you wanted the function to work like this:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
$x = foo("Hello World");
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To do this, you can't just pass a raw Perl string as the <tt>std::string *</tt> argument.
|
|
Instead, you have to create a temporary <tt>std::string</tt> object, copy the Perl string data into it, and
|
|
then pass a pointer to the object. To do this, simply specify the typemap with an extra parameter like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) std::string * <b>(std::string temp)</b> {
|
|
unsigned int len;
|
|
char *s;
|
|
s = SvPV($input,len); /* Extract string data */
|
|
temp.assign(s,len); /* Assign to temp */
|
|
$1 = &temp; /* Set argument to point to temp */
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, <tt>temp</tt> becomes a local variable in
|
|
the scope of the entire wrapper function. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
wrap_foo() {
|
|
std::string temp; <--- Declaration of temp goes here
|
|
...
|
|
|
|
/* Typemap code */
|
|
{
|
|
...
|
|
temp.assign(s,len);
|
|
...
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When you set <tt>temp</tt> to a value, it
|
|
persists for the duration of the wrapper function and gets
|
|
cleaned up automatically on exit.
|
|
</p>
|
|
|
|
<p>
|
|
It is perfectly safe to use more than one typemap involving local
|
|
variables in the same declaration. For example, you could declare a
|
|
function as :</p>
|
|
|
|
<div class="code"><pre>
|
|
void foo(std::string *x, std::string *y, std::string *z);
|
|
</pre></div>
|
|
|
|
<p>
|
|
This is safely handled because SWIG actually renames all local
|
|
variable references by appending an argument number suffix. Therefore, the
|
|
generated code would actually look like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
wrap_foo() {
|
|
int *arg1; /* Actual arguments */
|
|
int *arg2;
|
|
int *arg3;
|
|
std::string temp1; /* Locals declared in the typemap */
|
|
std::string temp2;
|
|
std::string temp3;
|
|
...
|
|
{
|
|
char *s;
|
|
unsigned int len;
|
|
...
|
|
temp1.assign(s,len);
|
|
arg1 = *temp1;
|
|
}
|
|
{
|
|
char *s;
|
|
unsigned int len;
|
|
...
|
|
temp2.assign(s,len);
|
|
arg2 = &temp2;
|
|
}
|
|
{
|
|
char *s;
|
|
unsigned int len;
|
|
...
|
|
temp3.assign(s,len);
|
|
arg3 = &temp3;
|
|
}
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Some typemaps do not recognize local variables (or they may simply not
|
|
apply). At this time, only typemaps that apply to argument conversion support this.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Note:</b>
|
|
</p>
|
|
|
|
<p>
|
|
When declaring a typemap for multiple types,
|
|
each type must have its own local variable declaration.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) const std::string *, std::string * (std::string temp) // NO!
|
|
// only std::string * has a local variable
|
|
// const std::string * does not (oops)
|
|
....
|
|
|
|
%typemap(in) const std::string * (std::string temp), std::string * (std::string temp) // Correct
|
|
....
|
|
</pre>
|
|
</div>
|
|
|
|
|
|
<H3><a name="Typemaps_special_variables"></a>10.4.3 Special variables</H3>
|
|
|
|
|
|
<p>
|
|
Within all typemaps, the following special variables are expanded.
|
|
</p>
|
|
|
|
<center>
|
|
<table border=1 summary="Typemap special variables">
|
|
<tr><th>Variable</th><th>Meaning</th></tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em></td>
|
|
<td>
|
|
A C local variable corresponding to type <em>n</em> in the typemap
|
|
pattern.
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$argnum</td>
|
|
<td>Argument number. Only available in typemaps related to argument conversion</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_name</td>
|
|
<td>Argument name</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_type</td>
|
|
<td>Real C datatype of type <em>n</em>.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_ltype</td>
|
|
<td>ltype of type <em>n</em></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_mangle</td>
|
|
<td>Mangled form of type <em>n</em>. For example <tt>_p_Foo</tt></td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_descriptor</td>
|
|
<td>Type descriptor structure for type <em>n</em>. For example
|
|
<tt>SWIGTYPE_p_Foo</tt>. This is primarily used when interacting with the
|
|
run-time type checker (described later).</td>
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<td>$*<em>n</em>_type</td>
|
|
<td>Real C datatype of type <em>n</em> with one pointer removed.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$*<em>n</em>_ltype</td>
|
|
<td>ltype of type <em>n</em> with one pointer removed.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$*<em>n</em>_mangle</td>
|
|
<td>Mangled form of type <em>n</em> with one pointer removed. </td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$*<em>n</em>_descriptor</td>
|
|
<td>Type descriptor structure for type <em>n</em> with one pointer removed.
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
<td>$&<em>n</em>_type</td>
|
|
<td>Real C datatype of type <em>n</em> with one pointer added.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$&<em>n</em>_ltype</td>
|
|
<td>ltype of type <em>n</em> with one pointer added.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$&<em>n</em>_mangle</td>
|
|
<td>Mangled form of type <em>n</em> with one pointer added.</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$&<em>n</em>_descriptor</td>
|
|
<td>Type descriptor structure for type <em>n</em> with one pointer added.
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>$<em>n</em>_basetype</td>
|
|
<td>Base typename with all pointers and qualifiers stripped.
|
|
</td>
|
|
</tr>
|
|
|
|
</table>
|
|
</center>
|
|
|
|
<p>
|
|
Within the table, $<em>n</em> refers to a specific type within the typemap specification. For example,
|
|
if you write this
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int *INPUT {
|
|
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then $1 refers to <tt>int *INPUT</tt>. If you have a typemap like this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (int argc, char *argv[]) {
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then $1 refers to <tt>int argc</tt> and $2 refers to <tt>char *argv[]</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
Substitutions related to types and names always fill in values from the actual code that was matched.
|
|
This is useful when a typemap might match multiple C datatype. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int, short, long {
|
|
$1 = ($1_ltype) PyInt_AsLong($input);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, <tt>$1_ltype</tt> is replaced with the datatype that is actually matched.
|
|
</p>
|
|
|
|
|
|
<p>
|
|
When typemap code is emitted, the C/C++ datatype of the special variables <tt>$1</tt> and
|
|
<tt>$2</tt> is always an "ltype." An "ltype" is simply a type that can legally appear
|
|
on the left-hand side of a C assignment operation. Here are a few examples of types
|
|
and ltypes:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
type ltype
|
|
------ ----------------
|
|
int int
|
|
const int int
|
|
const int * int *
|
|
int [4] int *
|
|
int [4][5] int (*)[5]
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In most cases a ltype is simply the C datatype with qualifiers stripped off. In addition,
|
|
arrays are converted into pointers.
|
|
</p>
|
|
|
|
<p>
|
|
Variables such as <tt>$&1_type</tt> and <tt>$*1_type</tt> are used to
|
|
safely modify the type by removing or adding pointers. Although not
|
|
needed in most typemaps, these substitutions are sometimes needed to properly
|
|
work with typemaps that convert values between pointers and values.
|
|
</p>
|
|
|
|
<p>
|
|
If necessary, type related substitutions can also be used when declaring locals. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int * ($*1_type temp) {
|
|
temp = PyInt_AsLong($input);
|
|
$1 = &temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
There is one word of caution about declaring local variables in this manner. If you declare a local variable
|
|
using a type substitution such as <tt>$1_ltype temp</tt>, it won't work like you expect for arrays and certain
|
|
kinds of pointers. For example, if you wrote this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int [10][20] {
|
|
$1_ltype temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then the declaration of <tt>temp</tt> will be expanded as
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int (*)[20] temp;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This is illegal C syntax and won't compile. There is currently no
|
|
straightforward way to work around this problem in SWIG due to the way
|
|
that typemap code is expanded and processed. However, one possible workaround
|
|
is to simply pick an alternative type such as <tt>void *</tt> and use
|
|
casts to get the correct type when needed. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int [10][20] {
|
|
void *temp;
|
|
...
|
|
(($1_ltype) temp)[i][j] = x; /* set a value */
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Another approach, which only works for arrays is to use the <tt>$1_basetype</tt> substitution. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int [10][20] {
|
|
$1_basetype temp[10][20];
|
|
...
|
|
temp[i][j] = x; /* set a value */
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Typemaps_nn25"></a>10.5 Common typemap methods</H2>
|
|
|
|
|
|
<p>
|
|
The set of typemaps recognized by a language module may vary. However,
|
|
the following typemap methods are nearly universal:
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn26"></a>10.5.1 "in" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "in" typemap is used to convert function arguments from the target language
|
|
to C. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int {
|
|
$1 = PyInt_AsLong($input);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The following special variables are available:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
$input - Input object holding value to be converted.
|
|
$symname - Name of function/method being wrapped
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This is probably the most commonly redefined typemap because it can be used
|
|
to implement customized conversions.
|
|
</p>
|
|
|
|
<p>
|
|
In addition, the "in" typemap allows the number of converted arguments to be
|
|
specified. The <tt>numinputs</tt> attributes facilitates this. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// Ignored argument.
|
|
%typemap(in, numinputs=0) int *out (int temp) {
|
|
$1 = &temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
At this time, only zero or one arguments may be converted.
|
|
When <tt>numinputs</tt> is set to 0, the argument is effectively ignored and cannot be supplied from the target language.
|
|
The argument is still required when making the C/C++ call and the above typemap
|
|
shows the value used is instead obtained from a locally declared variable called <tt>temp</tt>.
|
|
Usually <tt>numinputs</tt> is not specified, whereupon the default value is 1, that is, there is a one to one mapping of the number of arguments when used from the target language to the C/C++ call.
|
|
<a href="#Typemaps_multi_argument_typemaps">Multi-argument typemaps</a> provide a similar concept where the number of arguments mapped from the target language to C/C++ can be changed for more tha multiple adjacent C/C++ arguments.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Compatibility note: </b> Specifying <tt>numinputs=0</tt>
|
|
is the same as the old "ignore" typemap.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn27"></a>10.5.2 "typecheck" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "typecheck" typemap is used to support overloaded functions and methods. It merely checks an argument
|
|
to see whether or not it matches a specific type. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(typecheck,precedence=SWIG_TYPECHECK_INTEGER) int {
|
|
$1 = PyInt_Check($input) ? 1 : 0;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
If you define new "in" typemaps <em>and</em> 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."
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn28"></a>10.5.3 "out" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "out" typemap is used to convert function/method return values from C
|
|
into the target language. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) int {
|
|
$result = PyInt_FromLong($1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The following special variables are available.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
$result - Result object returned to target language.
|
|
$symname - Name of function/method being wrapped
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The "out" typemap supports an optional attribute flag called "optimal". This is for code optimisation and is detailed in the <a href="#Typemaps_optimal">Optimal code generation when returning by value</a> section.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn29"></a>10.5.4 "arginit" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "arginit" typemap is used to set the initial value of a function
|
|
argument--before any conversion has occurred. This is not normally
|
|
necessary, but might be useful in highly specialized applications.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// Set argument to NULL before any conversion occurs
|
|
%typemap(arginit) int *data {
|
|
$1 = NULL;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn30"></a>10.5.5 "default" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "default" typemap is used to turn an argument into a default
|
|
argument. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(default) int flags {
|
|
$1 = DEFAULT_FLAGS;
|
|
}
|
|
...
|
|
int foo(int x, int y, int flags);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The primary use of this typemap is to either change the wrapping of
|
|
default arguments or specify a default argument in a language where
|
|
they aren't supported (like C). Target languages that do not support
|
|
optional arguments, such as Java and C#, effectively ignore the value specified
|
|
by this typemap as all arguments must be given.
|
|
</p>
|
|
|
|
<p>
|
|
Once a default typemap has been applied to an argument, all arguments
|
|
that follow must have default values.
|
|
See the <a href="SWIG.html#SWIG_default_args">Default/optional arguments</a> section
|
|
for further information on default argument wrapping.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn31"></a>10.5.6 "check" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "check" typemap is used to supply value checking code during argument
|
|
conversion. The typemap is applied <em>after</em> arguments have been
|
|
converted. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(check) int positive {
|
|
if ($1 <= 0) {
|
|
SWIG_exception(SWIG_ValueError,"Expected positive value.");
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<H3><a name="Typemaps_nn32"></a>10.5.7 "argout" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "argout" typemap is used to return values from arguments. This
|
|
is most commonly used to write wrappers for C/C++ functions that need
|
|
to return multiple values. The "argout" typemap is almost always combined
|
|
with an "in" typemap---possibly to ignore the input value. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Set the input argument to point to a temporary variable */
|
|
%typemap(in, numinputs=0) int *out (int temp) {
|
|
$1 = &temp;
|
|
}
|
|
|
|
%typemap(argout) int *out {
|
|
// Append output value $1 to $result
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The following special variables are available.
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
$result - Result object returned to target language.
|
|
$input - The original input object passed.
|
|
$symname - Name of function/method being wrapped
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The code supplied to the "argout" typemap is always placed after
|
|
the "out" typemap. If multiple return values are used, the extra
|
|
return values are often appended to return value of the function.
|
|
</p>
|
|
|
|
<p>
|
|
See the <tt>typemaps.i</tt> library for examples.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn33"></a>10.5.8 "freearg" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "freearg" typemap is used to cleanup argument data. It is only
|
|
used when an argument might have allocated resources that need to be
|
|
cleaned up when the wrapper function exits. The "freearg" typemap
|
|
usually cleans up argument resources allocated by the "in" typemap.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// Get a list of integers
|
|
%typemap(in) int *items {
|
|
int nitems = Length($input);
|
|
$1 = (int *) malloc(sizeof(int)*nitems);
|
|
}
|
|
// Free the list
|
|
%typemap(freearg) int *items {
|
|
free($1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The "freearg" typemap inserted at the end of the wrapper function,
|
|
just before control is returned back to the target language. This
|
|
code is also placed into a special variable <tt>$cleanup</tt> that may
|
|
be used in other typemaps whenever a wrapper function needs to abort
|
|
prematurely.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn34"></a>10.5.9 "newfree" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "newfree" typemap is used in conjunction with the <tt>%newobject</tt>
|
|
directive and is used to deallocate memory used by the return result
|
|
of a function. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(newfree) string * {
|
|
delete $1;
|
|
}
|
|
%typemap(out) string * {
|
|
$result = PyString_FromString($1->c_str());
|
|
}
|
|
...
|
|
|
|
%newobject foo;
|
|
...
|
|
string *foo();
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
See <a href="Customization.html#ownership">Object ownership and %newobject</a> for further details.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn35"></a>10.5.10 "memberin" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "memberin" typemap is used to copy data from <em>an already converted input value</em>
|
|
into a structure member. It is typically used to handle array members and other special
|
|
cases. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(memberin) int [4] {
|
|
memmove($1, $input, 4*sizeof(int));
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It is rarely necessary to write "memberin" typemaps---SWIG already provides
|
|
a default implementation for arrays, strings, and other objects.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn36"></a>10.5.11 "varin" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "varin" typemap is used to convert objects in the target language to C for the
|
|
purposes of assigning to a C/C++ global variable. This is implementation specific.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn37"></a>10.5.12 "varout" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "varout" typemap is used to convert a C/C++ object to an object in the target
|
|
language when reading a C/C++ global variable. This is implementation specific.
|
|
</p>
|
|
|
|
<H3><a name="throws_typemap"></a>10.5.13 "throws" typemap</H3>
|
|
|
|
|
|
<p>
|
|
The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the <tt>%catches</tt> feature attached to the method.
|
|
It provides a default mechanism for handling C++ methods that have declared the exceptions they will throw.
|
|
The purpose of this typemap is to convert a C++ exception into an error or exception in the target language.
|
|
It is slightly different to the other typemaps as it is based around the exception type rather than the type of a parameter or variable.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(throws) const char * %{
|
|
PyErr_SetString(PyExc_RuntimeError, $1);
|
|
SWIG_fail;
|
|
%}
|
|
void bar() throw (const char *);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
As can be seen from the generated code below, SWIG generates an exception handler
|
|
with the catch block comprising the "throws" typemap content.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
...
|
|
try {
|
|
bar();
|
|
}
|
|
catch(char const *_e) {
|
|
PyErr_SetString(PyExc_RuntimeError, _e);
|
|
SWIG_fail;
|
|
|
|
}
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note that if your methods do not have an exception specification yet they do throw exceptions, SWIG cannot know how to deal with them.
|
|
For a neat way to handle these, see the <a href="Customization.html#exception">Exception handling with %exception</a> section.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_nn39"></a>10.6 Some typemap examples</H2>
|
|
|
|
|
|
<p>
|
|
This section contains a few examples. Consult language module documentation
|
|
for more examples.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn40"></a>10.6.1 Typemaps for arrays</H3>
|
|
|
|
|
|
<p>
|
|
A common use of typemaps is to provide support for C arrays appearing both as
|
|
arguments to functions and as structure members.
|
|
</p>
|
|
|
|
<p>
|
|
For example, suppose you had a function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
void set_vector(int type, float value[4]);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you wanted to handle <tt>float value[4]</tt> as a list of floats, you might write a typemap
|
|
similar to this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
|
|
%typemap(in) float value[4] (float temp[4]) {
|
|
int i;
|
|
if (!PySequence_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
|
return NULL;
|
|
}
|
|
if (PySequence_Length($input) != 4) {
|
|
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected 4 elements");
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < 4; i++) {
|
|
PyObject *o = PySequence_GetItem($input,i);
|
|
if (PyNumber_Check(o)) {
|
|
temp[i] = (float) PyFloat_AsDouble(o);
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
|
return NULL;
|
|
}
|
|
}
|
|
$1 = temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this example, the variable <tt>temp</tt> allocates a small array on the
|
|
C stack. The typemap then populates this array and passes it to the underlying C function.
|
|
</p>
|
|
|
|
<p>
|
|
When used from Python, the typemap allows the following type of function call:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> set_vector(type, [ 1, 2.5, 5, 20 ])
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you wanted to generalize the typemap to apply to arrays of all dimensions you might write this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) float value[ANY] (float temp[$1_dim0]) {
|
|
int i;
|
|
if (!PySequence_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
|
return NULL;
|
|
}
|
|
if (PySequence_Length($input) != $1_dim0) {
|
|
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < $1_dim0; i++) {
|
|
PyObject *o = PySequence_GetItem($input,i);
|
|
if (PyNumber_Check(o)) {
|
|
temp[i] = (float) PyFloat_AsDouble(o);
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
|
return NULL;
|
|
}
|
|
}
|
|
$1 = temp;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this example, the special variable <tt>$1_dim0</tt> is expanded with the actual
|
|
array dimensions. Multidimensional arrays can be matched in a similar manner. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) float matrix[ANY][ANY] (float temp[$1_dim0][$1_dim1]) {
|
|
... convert a 2d array ...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
For large arrays, it may be impractical to allocate storage on the stack using a temporary variable
|
|
as shown. To work with heap allocated data, the following technique can be used.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) float value[ANY] {
|
|
int i;
|
|
if (!PySequence_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
|
return NULL;
|
|
}
|
|
if (PySequence_Length($input) != $1_dim0) {
|
|
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
|
|
return NULL;
|
|
}
|
|
$1 = (float *) malloc($1_dim0*sizeof(float));
|
|
for (i = 0; i < $1_dim0; i++) {
|
|
PyObject *o = PySequence_GetItem($input,i);
|
|
if (PyNumber_Check(o)) {
|
|
$1[i] = (float) PyFloat_AsDouble(o);
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
|
free($1);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
%typemap(freearg) float value[ANY] {
|
|
if ($1) free($1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, an array is allocated using <tt>malloc</tt>. The <tt>freearg</tt> typemap is then used
|
|
to release the argument after the function has been called.
|
|
</p>
|
|
|
|
<p>
|
|
Another common use of array typemaps is to provide support for array structure members.
|
|
Due to subtle differences between pointers and arrays in C, you can't just "assign" to
|
|
a array structure member. Instead, you have to explicitly copy elements into the array.
|
|
For example, suppose you had a structure like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
struct SomeObject {
|
|
float value[4];
|
|
...
|
|
};
|
|
</pre></div>
|
|
|
|
<p>
|
|
When SWIG runs, it won't produce any code to set the <tt>vec</tt> member.
|
|
You may even get a warning message like this:
|
|
</p>
|
|
|
|
<div class="shell"><pre>
|
|
swig -python example.i
|
|
Generating wrappers for Python
|
|
example.i:10. Warning. Array member value will be read-only.
|
|
</pre></div>
|
|
|
|
<p>
|
|
These warning messages indicate that SWIG does not know how you want
|
|
to set the <tt>vec</tt> field.
|
|
</p>
|
|
|
|
<p>
|
|
To fix this, you can supply a special "memberin" typemap like this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%typemap(memberin) float [ANY] {
|
|
int i;
|
|
for (i = 0; i < $1_dim0; i++) {
|
|
$1[i] = $input[i];
|
|
}
|
|
}
|
|
</pre></div>
|
|
|
|
<p>
|
|
The memberin typemap is used to set a structure member from data that has already been converted
|
|
from the target language to C. In this case, <tt>$input</tt> is the local variable in which
|
|
converted input data is stored. This typemap then copies this data into the structure.
|
|
</p>
|
|
|
|
<p>
|
|
When combined with the earlier typemaps for arrays, the combination of the "in" and "memberin" typemap allows
|
|
the following usage:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> s = SomeObject()
|
|
>>> s.x = [1, 2.5, 5, 10]
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Related to structure member input, it may be desirable to return structure members as a new kind of
|
|
object. For example, in this example, you will get very odd program behavior where the structure member
|
|
can be set nicely, but reading the member simply returns a pointer:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> s = SomeObject()
|
|
>>> s.x = [1, 2.5, 5, 10]
|
|
>>> print s.x
|
|
_1008fea8_p_float
|
|
>>>
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To fix this, you can write an "out" typemap. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) float [ANY] {
|
|
int i;
|
|
$result = PyList_New($1_dim0);
|
|
for (i = 0; i < $1_dim0; i++) {
|
|
PyObject *o = PyFloat_FromDouble((double) $1[i]);
|
|
PyList_SetItem($result,i,o);
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Now, you will find that member access is quite nice:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> s = SomeObject()
|
|
>>> s.x = [1, 2.5, 5, 10]
|
|
>>> print s.x
|
|
[ 1, 2.5, 5, 10]
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
<b>Compatibility Note:</b> SWIG1.1 used to provide a special "memberout" typemap. However, it was mostly
|
|
useless and has since been eliminated. To return structure members, simply use the "out" typemap.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn41"></a>10.6.2 Implementing constraints with typemaps</H3>
|
|
|
|
|
|
<p>
|
|
One particularly interesting application of typemaps is the
|
|
implementation of argument constraints. This can be done with the
|
|
"check" typemap. When used, this allows you to provide code for
|
|
checking the values of function arguments. For example :</p>
|
|
|
|
<div class="code"><pre>
|
|
%module math
|
|
|
|
%typemap(check) double posdouble {
|
|
if ($1 < 0) {
|
|
croak("Expecting a positive number");
|
|
}
|
|
}
|
|
|
|
...
|
|
double sqrt(double posdouble);
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
This provides a sanity check to your wrapper function. If a negative
|
|
number is passed to this function, a Perl exception will be raised and
|
|
your program terminated with an error message.</p>
|
|
|
|
<p>
|
|
This kind of checking can be particularly useful when working with
|
|
pointers. For example :</p>
|
|
|
|
<div class="code"><pre>
|
|
%typemap(check) Vector * {
|
|
if ($1 == 0) {
|
|
PyErr_SetString(PyExc_TypeError,"NULL Pointer not allowed");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
</pre></div>
|
|
|
|
<p>
|
|
will prevent any function involving a <tt>Vector *</tt> from accepting
|
|
a NULL pointer. As a result, SWIG can often prevent a potential
|
|
segmentation faults or other run-time problems by raising an exception
|
|
rather than blindly passing values to the underlying C/C++ program.</p>
|
|
|
|
<p>
|
|
Note: A more advanced constraint checking system is in development. Stay tuned.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_nn43"></a>10.7 Typemaps for multiple languages</H2>
|
|
|
|
|
|
<p>
|
|
The code within typemaps is usually language dependent,
|
|
however, many languages support the same typemaps.
|
|
In order to distinguish typemaps across different languages, the preprocessor should be used.
|
|
For example, the "in" typemap for Perl and Ruby could be written as:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
#if defined(SWIGPERL)
|
|
%typemap(in) int "$1 = ($1_ltype) SvIV($input);"
|
|
#elif defined(SWIGRUBY)
|
|
%typemap(in) int "$1 = NUM2INT($input);"
|
|
#else
|
|
#warning no "in" typemap defined
|
|
#endif
|
|
</pre></div>
|
|
|
|
<p>
|
|
The full set of language specific macros is defined in the <a href="Preprocessor.html#Preprocessor_condition_compilation">Conditional Compilation</a> section.
|
|
The example above also shows a common approach of issuing a warning for an as yet unsupported language.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Compatibility note: </b> In SWIG-1.1 different languages could be distinguished with the language name being put within the <tt>%typemap</tt> directive, for example, <br>
|
|
<tt>%typemap(ruby,in) int "$1 = NUM2INT($input);"</tt>.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_optimal"></a>10.8 Optimal code generation when returning by value</H2>
|
|
|
|
|
|
<p>
|
|
The "out" typemap is the main typemap for return types.
|
|
This typemap supports an optional attribute flag called "optimal", which is for reducing
|
|
temporary variables and the amount of generated code.
|
|
It only really makes a difference when returning objects by value and it cannot always be used,
|
|
as explained later on.
|
|
</p>
|
|
|
|
<p>
|
|
When a function returns an object by value, SWIG generates code that instantiates the default
|
|
type on the stack then assigns the value returned by the function call to it.
|
|
A copy of this object is then made on the heap and this is what is ultimately stored and
|
|
used from the target language.
|
|
This will be clearer considering an example.
|
|
Consider running the following code through SWIG:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out) SWIGTYPE %{
|
|
$result = new $1_ltype((const $1_ltype &)$1);
|
|
%}
|
|
|
|
%inline %{
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
struct XX {
|
|
XX() { cout << "XX()" << endl; }
|
|
XX(int i) { cout << "XX(" << i << ")" << endl; }
|
|
XX(const XX &other) { cout << "XX(const XX &)" << endl; }
|
|
XX & operator =(const XX &other) { cout << "operator=(const XX &)" << endl; return *this; }
|
|
~XX() { cout << "~XX()" << endl; }
|
|
static XX create() {
|
|
return XX(0);
|
|
}
|
|
};
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The "out" typemap shown is the default typemap for C# when returning by objects by value.
|
|
When making a call to <tt>XX::create()</tt> from C#, the output is as follows:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
XX()
|
|
XX(0)
|
|
operator=(const XX &)
|
|
~XX()
|
|
XX(const XX &)
|
|
~XX()
|
|
~XX()
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note that three objects are being created as well as an assignment.
|
|
Wouldn't it be great if the <tt>XX::create()</tt> method was the only time a constructor was called?
|
|
As the method returns by value, this is asking a lot and the code that SWIG generates by default
|
|
makes it impossible for the compiler to make this type of optimisation.
|
|
However, this is where the "optimal" attribute in the "out" typemap can help out.
|
|
If the typemap code is kept the same and just the "optimal" attribute specified like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(out, optimal="1") SWIGTYPE %{
|
|
$result = new $1_ltype((const $1_ltype &)$1);
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then when the code is run again, the output is simply:
|
|
</P>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
XX(0)
|
|
~XX()
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
How the "optimal" attribute works is best explained using the generated code.
|
|
Without "optimal", the generated code is:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
|
|
void * jresult ;
|
|
XX result;
|
|
result = XX::create();
|
|
jresult = new XX((const XX &)result);
|
|
return jresult;
|
|
}
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
With the "optimal" attribute, the code is:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
|
|
void * jresult ;
|
|
jresult = new XX((const XX &)XX::create());
|
|
return jresult;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The major difference is the <tt>result</tt> temporary variable holding the value returned from <tt>XX::create()</tt> is no longer generated and instead the copy constructor call is made directly from
|
|
the value returned by <tt>XX::create()</tt>.
|
|
With modern compiler optimisations turned on, the copy is not actually done, in fact the object is never created
|
|
on the stack in <tt>XX::create()</tt> at all, it is simply created directly on the heap.
|
|
In the first instance, the <tt>$1</tt> special variable in the typemap is expanded into <tt>result</tt>.
|
|
In the second instance, <tt>$1</tt> is expanded into <tt>XX::create()</tt> and this is essentially
|
|
what the "optimal" attribute is telling SWIG to do.
|
|
</p>
|
|
|
|
<p>
|
|
This kind of optimisation is not turned on by default as it has a number of restrictions.
|
|
Firstly, some code cannot be condensed into a simple call for passing into the copy constructor.
|
|
One common occurrence is when <a href="Customization.html#exception">%exception</a> is used.
|
|
Consider adding the following <tt>%exception</tt> to the example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%exception XX::create() %{
|
|
try {
|
|
$action
|
|
} catch(const std::exception &e) {
|
|
cout << e.what() << endl;
|
|
}
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
SWIG can detect when the "optimal" attribute cannot be used and will ignore it and in this case will issue the following warning:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
example.i:28: Warning(474): Method XX::create() usage of the optimal attribute in the out
|
|
typemap at example.i:14 ignored as the following cannot be used to generate optimal code:
|
|
try {
|
|
result = XX::create();
|
|
} catch(const std::exception &e) {
|
|
cout << e.what() << endl;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It should be clear that the above code cannot be used as the argument to the copy constructor call, ie for the <tt>$1</tt> substitution.
|
|
</p>
|
|
|
|
<p>
|
|
Secondly, if the typemaps uses <tt>$1</tt> more than once, then multiple calls to the wrapped function
|
|
will be made. Obviously that is not very optimal.
|
|
In fact SWIG attempts to detect this and will issue a warning something like:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
example.i:21: Warning(475): Multiple calls to XX::create() might be generated due to
|
|
optimal attribute usage in the out typemap at example.i:7.
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
However, it doesn't always get it right, for example when <tt>$1</tt> is within some commented out code.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_multi_argument_typemaps"></a>10.9 Multi-argument typemaps</H2>
|
|
|
|
|
|
<p>
|
|
So far, the typemaps presented have focused on the problem of dealing with
|
|
single values. For example, converting a single input object to a single argument
|
|
in a function call. However, certain conversion problems are difficult to handle
|
|
in this manner. As an example, consider the example at the very beginning of this
|
|
chapter:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int foo(int argc, char *argv[]);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Suppose that you wanted to wrap this function so that it accepted a single
|
|
list of strings like this:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> foo(["ale","lager","stout"])
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To do this, you not only need to map a list of strings to <tt> char *argv[]</tt>, but the
|
|
value of <tt>int argc</tt> is implicitly determined by the length of the list. Using only simple
|
|
typemaps, this type of conversion is possible, but extremely painful. Therefore, SWIG1.3
|
|
introduces the notion of multi-argument typemaps.
|
|
</p>
|
|
|
|
<p>
|
|
A multi-argument typemap is a conversion rule that specifies how to
|
|
convert a <em>single</em> object in the target language to set of
|
|
consecutive function arguments in C/C++. For example, the following multi-argument
|
|
maps perform the conversion described for the above example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (int argc, char *argv[]) {
|
|
int i;
|
|
if (!PyList_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError, "Expecting a list");
|
|
return NULL;
|
|
}
|
|
$1 = PyList_Size($input);
|
|
$2 = (char **) malloc(($1+1)*sizeof(char *));
|
|
for (i = 0; i < $1; i++) {
|
|
PyObject *s = PyList_GetItem($input,i);
|
|
if (!PyString_Check(s)) {
|
|
free($2);
|
|
PyErr_SetString(PyExc_ValueError, "List items must be strings");
|
|
return NULL;
|
|
}
|
|
$2[i] = PyString_AsString(s);
|
|
}
|
|
$2[i] = 0;
|
|
}
|
|
|
|
%typemap(freearg) (int argc, char *argv[]) {
|
|
if ($2) free($2);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A multi-argument map is always specified by surrounding the arguments with parentheses as shown.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (int argc, char *argv[]) { ... }
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Within the typemap code, the variables <tt>$1</tt>, <tt>$2</tt>, and so forth refer to each type
|
|
in the map. All of the usual substitutions apply--just use the appropriate <tt>$1</tt> or <tt>$2</tt>
|
|
prefix on the variable name (e.g., <tt>$2_type</tt>, <tt>$1_ltype</tt>, etc.)
|
|
</p>
|
|
|
|
<p>
|
|
Multi-argument typemaps always have precedence over simple typemaps and SWIG always performs longest-match searching.
|
|
Therefore, you will get the following behavior:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int argc { ... typemap 1 ... }
|
|
%typemap(in) (int argc, char *argv[]) { ... typemap 2 ... }
|
|
%typemap(in) (int argc, char *argv[], char *env[]) { ... typemap 3 ... }
|
|
|
|
int foo(int argc, char *argv[]); // Uses typemap 2
|
|
int bar(int argc, int x); // Uses typemap 1
|
|
int spam(int argc, char *argv[], char *env[]); // Uses typemap 3
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
It should be stressed that multi-argument typemaps can appear anywhere in a function declaration and can
|
|
appear more than once. For example, you could write this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (int scount, char *swords[]) { ... }
|
|
%typemap(in) (int wcount, char *words[]) { ... }
|
|
|
|
void search_words(int scount, char *swords[], int wcount, char *words[], int maxcount);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Other directives such as <tt>%apply</tt> and <tt>%clear</tt> also work with multi-argument maps. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%apply (int argc, char *argv[]) {
|
|
(int scount, char *swords[]),
|
|
(int wcount, char *words[])
|
|
};
|
|
...
|
|
%clear (int scount, char *swords[]), (int wcount, char *words[]);
|
|
...
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Although multi-argument typemaps may seem like an exotic, little used feature, there
|
|
are several situations where they make sense. First, suppose you wanted to wrap
|
|
functions similar to the low-level <tt>read()</tt> and <tt>write()</tt> system calls.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
typedef unsigned int size_t;
|
|
|
|
int read(int fd, void *rbuffer, size_t len);
|
|
int write(int fd, void *wbuffer, size_t len);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
As is, the only way to use the functions would be to allocate memory and pass some kind of pointer
|
|
as the second argument---a process that might require the use of a helper function. However, using
|
|
multi-argument maps, the functions can be transformed into something more natural. For example, you
|
|
might write typemaps like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// typemap for an outgoing buffer
|
|
%typemap(in) (void *wbuffer, size_t len) {
|
|
if (!PyString_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError, "Expecting a string");
|
|
return NULL;
|
|
}
|
|
$1 = (void *) PyString_AsString($input);
|
|
$2 = PyString_Size($input);
|
|
}
|
|
|
|
// typemap for an incoming buffer
|
|
%typemap(in) (void *rbuffer, size_t len) {
|
|
if (!PyInt_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError, "Expecting an integer");
|
|
return NULL;
|
|
}
|
|
$2 = PyInt_AsLong($input);
|
|
if ($2 < 0) {
|
|
PyErr_SetString(PyExc_ValueError, "Positive integer expected");
|
|
return NULL;
|
|
}
|
|
$1 = (void *) malloc($2);
|
|
}
|
|
|
|
// Return the buffer. Discarding any previous return result
|
|
%typemap(argout) (void *rbuffer, size_t len) {
|
|
Py_XDECREF($result); /* Blow away any previous result */
|
|
if (result < 0) { /* Check for I/O error */
|
|
free($1);
|
|
PyErr_SetFromErrno(PyExc_IOError);
|
|
return NULL;
|
|
}
|
|
$result = PyString_FromStringAndSize($1,result);
|
|
free($1);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
(note: In the above example, <tt>$result</tt> and <tt>result</tt> are two different variables.
|
|
<tt>result</tt> is the real C datatype that was returned by the function. <tt>$result</tt> is the
|
|
scripting language object being returned to the interpreter.).
|
|
</p>
|
|
|
|
<p>
|
|
Now, in a script, you can write code that simply passes buffers as strings like this:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
>>> f = example.open("Makefile")
|
|
>>> example.read(f,40)
|
|
'TOP = ../..\nSWIG = $(TOP)/.'
|
|
>>> example.read(f,40)
|
|
'./swig\nSRCS = example.c\nTARGET '
|
|
>>> example.close(f)
|
|
0
|
|
>>> g = example.open("foo", example.O_WRONLY | example.O_CREAT, 0644)
|
|
>>> example.write(g,"Hello world\n")
|
|
12
|
|
>>> example.write(g,"This is a test\n")
|
|
15
|
|
>>> example.close(g)
|
|
0
|
|
>>>
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A number of multi-argument typemap problems also arise in libraries that
|
|
perform matrix-calculations--especially if they are mapped onto low-level Fortran
|
|
or C code. For example, you might have a function like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int is_symmetric(double *mat, int rows, int columns);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, you might want to pass some kind of higher-level object as an matrix. To do
|
|
this, you could write a multi-argument typemap like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) (double *mat, int rows, int columns) {
|
|
MatrixObject *a;
|
|
a = GetMatrixFromObject($input); /* Get matrix somehow */
|
|
|
|
/* Get matrix properties */
|
|
$1 = GetPointer(a);
|
|
$2 = GetRows(a);
|
|
$3 = GetColumns(a);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
This kind of technique can be used to hook into scripting-language matrix packages such as
|
|
Numeric Python. However, it should also be stressed that some care is in order. For example,
|
|
when crossing languages you may need to worry about issues such as row-major vs. column-major
|
|
ordering (and perform conversions if needed).
|
|
</p>
|
|
|
|
<H2><a name="runtime_type_checker"></a>10.10 The run-time type checker</H2>
|
|
|
|
|
|
<p>
|
|
Most scripting languages need type information at run-time. This type information
|
|
can include how to construct types, how to garbage collect types, and the inheritance
|
|
relationships between types. If the language interface does not provide its own type
|
|
information storage, the generated SWIG code needs to provide it.
|
|
</p>
|
|
|
|
<p>
|
|
Requirements for the type system:
|
|
</p>
|
|
<ul>
|
|
<li>Store inheritance and type equivalence information and be able to correctly
|
|
re-create the type pointer.</li>
|
|
<li>Share type information between modules.</li>
|
|
<li>Modules can be loaded in any order, irregardless of actual type
|
|
dependency.</li>
|
|
<li>Avoid the use of dynamically allocated memory, and library/system calls in general.</li>
|
|
<li>Provide a reasonably fast implementation, minimizing the lookup time for all
|
|
language modules.</li>
|
|
<li>Custom, language specific information can be attached to types.</li>
|
|
<li>Modules can be unloaded from the type system.</li>
|
|
</ul>
|
|
|
|
<H3><a name="Typemaps_nn45"></a>10.10.1 Implementation</H3>
|
|
|
|
|
|
<p>
|
|
The run-time type checker is used by many, but not all, of SWIG's supported target languages.
|
|
The run-time type checker features
|
|
are not required and are thus not used for strongly typed languages such as Java and C#.
|
|
The scripting and scheme based languages rely on it and it forms
|
|
a critical part of SWIG's operation for these languages.
|
|
</p>
|
|
|
|
<p>
|
|
When pointers, arrays, and objects are wrapped by SWIG, they are normally converted
|
|
into typed pointer objects. For example, an instance of <tt>Foo *</tt> might be
|
|
a string encoded like this:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
_108e688_p_Foo
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
At a basic level, the type checker simply restores some type-safety to
|
|
extension modules. However, the type checker is also responsible for
|
|
making sure that wrapped C++ classes are handled
|
|
correctly---especially when inheritance is used. This is especially
|
|
important when an extension module makes use of multiple inheritance.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Foo {
|
|
int x;
|
|
};
|
|
|
|
class Bar {
|
|
int y;
|
|
};
|
|
|
|
class FooBar : public Foo, public Bar {
|
|
int z;
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When the class <tt>FooBar</tt> is organized in memory, it contains the contents
|
|
of the classes <tt>Foo</tt> and <tt>Bar</tt> as well as its own data members. For example:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
FooBar --> | -----------| <-- Foo
|
|
| int x |
|
|
|------------| <-- Bar
|
|
| int y |
|
|
|------------|
|
|
| int z |
|
|
|------------|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Because of the way that base class data is stacked together, the
|
|
casting of a <tt>Foobar *</tt> to either of the base classes may
|
|
change the actual value of the pointer. This means that it is
|
|
generally not safe to represent pointers using a simple integer or a
|
|
bare <tt>void *</tt>---type tags are needed to implement correct
|
|
handling of pointer values (and to make adjustments when needed).
|
|
</p>
|
|
|
|
<p>
|
|
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:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_Foo,1)) == -1) return NULL;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this code, <tt>SWIGTYPE_p_Foo</tt> is the type descriptor that
|
|
describes <tt>Foo *</tt>. The type descriptor is actually a pointer to a
|
|
structure that contains information about the type name to use in the
|
|
target language, a list of equivalent typenames (via typedef or
|
|
inheritance), and pointer value handling information (if applicable).
|
|
The <tt>SWIG_ConvertPtr()</tt> 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
|
|
function depends on the target language (see language specific chapters for details).
|
|
</p>
|
|
|
|
<p>
|
|
The actual type code is in swigrun.swg, and gets inserted near the top of the generated
|
|
swig wrapper file. The phrase "a type X that can cast into a type Y" means
|
|
that given a type X, it can be converted into a type Y. In other words, X is a derived
|
|
class of Y or X is a typedef of Y. The structure to store type information looks like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Structure to store information on one type */
|
|
typedef struct swig_type_info {
|
|
const char *name; /* mangled name of this type */
|
|
const char *str; /* human readable name for this type */
|
|
swig_dycast_func dcast; /* dynamic cast function down a hierarchy */
|
|
struct swig_cast_info *cast; /* Linked list of types that can cast into this type */
|
|
void *clientdata; /* Language specific type data */
|
|
} swig_type_info;
|
|
|
|
/* Structure to store a type and conversion function used for casting */
|
|
typedef struct swig_cast_info {
|
|
swig_type_info *type; /* pointer to type that is equivalent to this type */
|
|
swig_converter_func converter; /* function to cast the void pointers */
|
|
struct swig_cast_info *next; /* pointer to next cast in linked list */
|
|
struct swig_cast_info *prev; /* pointer to the previous cast */
|
|
} swig_cast_info;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Each <tt>swig_type_info</tt> stores a linked list of types that it is equivalent to. Each entry in this
|
|
doubly linked list stores a pointer back to another swig_type_info structure,
|
|
along with a pointer to a conversion function. This conversion function is used
|
|
to solve the above problem of the FooBar class, correctly returning a pointer to
|
|
the type we want.
|
|
</p>
|
|
|
|
<p>
|
|
The basic problem we need to solve is verifying and building arguments passed to functions.
|
|
So going back to the <tt>SWIG_ConvertPtr()</tt> function example from above, we are
|
|
expecting a <tt>Foo *</tt> and need to
|
|
check if <tt>obj0</tt> is in fact a <tt>Foo *</tt>. From before, <tt>SWIGTYPE_p_Foo</tt> is just
|
|
a pointer to the <tt>swig_type_info</tt> structure describing <tt>Foo *</tt>. So we loop through the
|
|
linked list of <tt>swig_cast_info</tt> structures attached to <tt>SWIGTYPE_p_Foo</tt>. If we see that the type of <tt>obj0</tt> is in the
|
|
linked list, we pass the object through the associated conversion function and
|
|
then return a positive. If we reach the end of the linked list without a match,
|
|
then <tt>obj0</tt> can not be converted to a <tt>Foo *</tt> and an error is generated.
|
|
</p>
|
|
|
|
<p>
|
|
Another issue needing to be addressed is sharing type information between multiple modules.
|
|
More explicitly, we need
|
|
to have ONE <tt>swig_type_info</tt> for each type. If two modules both use the type, the
|
|
second module loaded must lookup and use the swig_type_info structure from the module already loaded.
|
|
Because no dynamic memory is used and the circular dependencies of the
|
|
casting information, loading the type information is somewhat tricky, and not explained here.
|
|
A complete description is in the <tt>Lib/swiginit.swg</tt> file (and near the top of any generated file).
|
|
</p>
|
|
|
|
<p>
|
|
Each module has one swig_module_info structure which looks like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* Structure used to store module information
|
|
* Each module generates one structure like this, and the runtime collects
|
|
* all of these structures and stores them in a circularly linked list.*/
|
|
typedef struct swig_module_info {
|
|
swig_type_info **types; /* Array of pointers to swig_type_info structs in this module */
|
|
int size; /* Number of types in this module */
|
|
struct swig_module_info *next; /* Pointer to next element in circularly linked list */
|
|
swig_type_info **type_initial; /* Array of initially generated type structures */
|
|
swig_cast_info **cast_initial; /* Array of initially generated casting structures */
|
|
void *clientdata; /* Language specific module data */
|
|
} swig_module_info;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Each module stores an array of pointers to <tt>swig_type_info</tt> structures and the number of
|
|
types in this module. So when a second module is loaded, it finds the <tt>swig_module_info</tt>
|
|
structure for the first module and searches the array of types. If any of its own
|
|
types are in the first module and have already been loaded, it uses those <tt>swig_type_info</tt>
|
|
structures rather than creating new ones. These <tt>swig_module_info</tt>
|
|
structures are chained together in a circularly linked list.
|
|
</p>
|
|
|
|
<H3><a name="Typemaps_nn46"></a>10.10.2 Usage</H3>
|
|
|
|
|
|
<p>This section covers how to use these functions from typemaps. To learn how to
|
|
call these functions from external files (not the generated _wrap.c file), see
|
|
the <a href="Modules.html#external_run_time">External access to the run-time system</a>
|
|
section.</p>
|
|
|
|
<p>When pointers are converted in a typemap, the typemap code often looks
|
|
similar to this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) Foo * {
|
|
if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) return NULL;
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The most critical part is the typemap is the use of the <tt>$1_descriptor</tt>
|
|
special variable. When placed in a typemap, this is expanded into the
|
|
<tt>SWIGTYPE_*</tt> type descriptor object above. As a general rule,
|
|
you should always use <tt>$1_descriptor</tt> instead of trying to
|
|
hard-code the type descriptor name directly.
|
|
</p>
|
|
|
|
<p>
|
|
There is another reason why you should always use the
|
|
<tt>$1_descriptor</tt> variable. When this special variable is
|
|
expanded, SWIG marks the corresponding type as "in use." When
|
|
type-tables and type information is emitted in the wrapper file,
|
|
descriptor information is only generated for those datatypes that were
|
|
actually used in the interface. This greatly reduces the size of the
|
|
type tables and improves efficiency.
|
|
</p>
|
|
|
|
<p>
|
|
Occasionally, you might need to write a typemap that needs to convert
|
|
pointers of other types. To handle this, a special macro substitution
|
|
<tt>$descriptor(type)</tt> can be used to generate the SWIG type
|
|
descriptor name for any C datatype. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) Foo * {
|
|
if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor)) == -1) {
|
|
Bar *temp;
|
|
if ((SWIG_ConvertPtr($input, (void **) &temp, <b>$descriptor(Bar *)</b>) == -1) {
|
|
return NULL;
|
|
}
|
|
$1 = (Foo *) temp;
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The primary use of <tt>$descriptor(type)</tt> is when writing typemaps for container
|
|
objects and other complex data structures. There are some restrictions on the argument---namely it must
|
|
be a fully defined C datatype. It can not be any of the special typemap variables.
|
|
</p>
|
|
|
|
<p>
|
|
In certain cases, SWIG may not generate type-descriptors like you expect. For example,
|
|
if you are converting pointers in some non-standard way or working with an unusual
|
|
combination of interface files and modules, you may find that SWIG omits information
|
|
for a specific type descriptor. To fix this, you may need to use the <tt>%types</tt> directive.
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%types(int *, short *, long *, float *, double *);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
When <tt>%types</tt> is used, SWIG generates type-descriptor
|
|
information even if those datatypes never appear elsewhere in the
|
|
interface file.
|
|
</p>
|
|
|
|
<p>
|
|
Further details about the run-time type checking can be found in the documentation for
|
|
individual language modules. Reading the source code may also help. The file
|
|
<tt>Lib/swigrun.swg</tt> in the SWIG library contains all of the source code for
|
|
type-checking. This code is also included in every generated wrapped file so you
|
|
probably just look at the output of SWIG to get a better sense for how types are
|
|
managed.
|
|
</p>
|
|
|
|
<H2><a name="Typemaps_overloading"></a>10.11 Typemaps and overloading</H2>
|
|
|
|
|
|
<p>
|
|
In many target languages, SWIG fully supports C++ overloaded methods and functions. For example,
|
|
if you have a collection of functions like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
int foo(int x);
|
|
int foo(double x);
|
|
int foo(char *s, int y);
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
You can access the functions in a normal way from the scripting interpreter:
|
|
</p>
|
|
|
|
<div class="targetlang">
|
|
<pre>
|
|
# 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)
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To implement overloading, SWIG generates a separate wrapper function for each overloaded method.
|
|
For example, the above functions would produce something roughly like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// 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);
|
|
}
|
|
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Next, a dynamic dispatch function is generated:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
_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");
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
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 "<a href="SWIGPlus.html#SWIGPlus">SWIG and C++</a>" chapter. What isn't mentioned in that chapter
|
|
is the mechanism by which it is implemented---as a collection of typemaps.
|
|
</p>
|
|
|
|
<p>
|
|
To support dynamic dispatch, SWIG first defines a general purpose type hierarchy as follows:
|
|
</p>
|
|
|
|
<div class="diagram">
|
|
<pre>
|
|
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
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
(These precedence levels are defined in <tt>swig.swg</tt>, a library file that's included by all target language modules.)
|
|
</p>
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
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:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
/* 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);
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
Finally, to generate the dynamic dispatch function, SWIG uses the following algorithm:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Overloaded methods are first sorted by the number of required arguments.</li>
|
|
<li>Methods with the same number of arguments are then sorted by precedence values of argument types.</li>
|
|
<li>Typecheck typemaps are then emitted to produce a dispatch function that checks arguments in the correct order.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
If you haven't written any typemaps of your own, it is unnecessary to worry about the typechecking rules.
|
|
However, if you have written new input typemaps, you might have to supply a typechecking rule as well.
|
|
An easy way to do this is to simply copy one of the existing typechecking rules.
|
|
Here is an example,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
// 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 *;
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Notes:</b>
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Typecheck typemaps are not used for non-overloaded methods. Because of this, it is
|
|
still always necessary to check types in any "in" typemaps.
|
|
</li>
|
|
|
|
<li>The dynamic dispatch process is only meant to be a heuristic. There are many corner
|
|
cases where SWIG simply can't disambiguate types to the same degree as C++. The only way to
|
|
resolve this ambiguity is to use the %rename directive to rename one of the overloaded methods (effectively
|
|
eliminating overloading).
|
|
</li>
|
|
|
|
<li>
|
|
Typechecking may be partial. For example, if working with arrays, the typecheck code might
|
|
simply check the type of the first array element and use that to dispatch to the correct function.
|
|
Subsequent "in" typemaps would then perform more extensive type-checking.
|
|
</li>
|
|
|
|
<li>Make sure you read the section on overloading in the "<a href="SWIGPlus.html#SWIGPlus">SWIG and C++</a>" chapter.
|
|
</li>
|
|
</ul>
|
|
|
|
<H2><a name="Typemaps_nn48"></a>10.12 More about <tt>%apply</tt> and <tt>%clear</tt></H2>
|
|
|
|
|
|
<p>
|
|
In order to implement certain kinds of program behavior, it is sometimes necessary to
|
|
write sets of typemaps. For example, to support output arguments, one often writes
|
|
a set of typemaps like this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in,numinputs=0) int *OUTPUT (int temp) {
|
|
$1 = &temp;
|
|
}
|
|
%typemap(argout) int *OUTPUT {
|
|
// return value somehow
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
To make it easier to apply the typemap to different argument types and names, the <tt>%apply</tt> directive
|
|
performs a copy of all typemaps from one type to another. For example, if you specify this,
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%apply int *OUTPUT { int *retvalue, int32 *output };
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
then all of the <tt>int *OUTPUT</tt> typemaps are copied to <tt>int *retvalue</tt> and <tt>int32 *output</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
However, there is a subtle aspect of <tt>%apply</tt> that needs more description. Namely, <tt>%apply</tt> does not
|
|
overwrite a typemap rule if it is already defined for the target datatype. This behavior allows you to do two things:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>You can specialize parts of a complex typemap rule by first defining a few typemaps and then using
|
|
<tt>%apply</tt> to incorporate the remaining pieces.
|
|
</li>
|
|
|
|
<li>Sets of different typemaps can be applied to the same datatype using repeated <tt>%apply</tt> directives.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>
|
|
For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int *INPUT (int temp) {
|
|
temp = ... get value from $input ...;
|
|
$1 = &temp;
|
|
}
|
|
|
|
%typemap(check) int *POSITIVE {
|
|
if (*$1 <= 0) {
|
|
SWIG_exception(SWIG_ValueError,"Expected a positive number!\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
...
|
|
%apply int *INPUT { int *invalue };
|
|
%apply int *POSITIVE { int *invalue };
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Since <tt>%apply</tt> does not overwrite or replace any existing rules, the only way to reset behavior is to
|
|
use the <tt>%clear</tt> directive. <tt>%clear</tt> removes all typemap rules defined for a specific datatype. For
|
|
example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%clear int *invalue;
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Typemaps_nn49"></a>10.13 Reducing wrapper code size</H2>
|
|
|
|
|
|
<p>
|
|
Since the code supplied to a typemap is inlined directly into wrapper functions, typemaps can result
|
|
in a tremendous amount of code bloat. For example, consider this typemap for an array:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) float [ANY] {
|
|
int i;
|
|
if (!PySequence_Check($input)) {
|
|
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
|
return NULL;
|
|
}
|
|
if (PySequence_Length($input) != $1_dim0) {
|
|
PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
|
|
return NULL;
|
|
}
|
|
$1 = (float) malloc($1_dim0*sizeof(float));
|
|
for (i = 0; i < $1_dim0; i++) {
|
|
PyObject *o = PySequence_GetItem($input,i);
|
|
if (PyNumber_Check(o)) {
|
|
$1[i] = (float) PyFloat_AsDouble(o);
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
|
free(result);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
If you had a large interface with hundreds of functions all accepting
|
|
array parameters, this typemap would be replicated
|
|
repeatedly--generating a huge amount of code. A better approach might
|
|
be to consolidate some of the typemap into a function. For example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%{
|
|
/* Define a helper function */
|
|
static float *
|
|
convert_float_array(PyObject *input, int size) {
|
|
int i;
|
|
float *result;
|
|
if (!PySequence_Check(input)) {
|
|
PyErr_SetString(PyExc_ValueError,"Expected a sequence");
|
|
return NULL;
|
|
}
|
|
if (PySequence_Length(input) != size) {
|
|
PyErr_SetString(PyExc_ValueError,"Size mismatch. ");
|
|
return NULL;
|
|
}
|
|
result = (float) malloc(size*sizeof(float));
|
|
for (i = 0; i < size; i++) {
|
|
PyObject *o = PySequence_GetItem(input,i);
|
|
if (PyNumber_Check(o)) {
|
|
result[i] = (float) PyFloat_AsDouble(o);
|
|
} else {
|
|
PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");
|
|
free(result);
|
|
return NULL;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
%}
|
|
|
|
%typemap(in) float [ANY] {
|
|
$1 = convert_float_array($input, $1_dim0);
|
|
if (!$1) return NULL;
|
|
}
|
|
%}
|
|
</pre>
|
|
</div>
|
|
|
|
<H2><a name="Typemaps_nn47"></a>10.14 Passing data between typemaps</H2>
|
|
|
|
|
|
<p>
|
|
It is also important to note that the primary use of local variables
|
|
is to create stack-allocated objects for temporary use inside a
|
|
wrapper function (this is faster and less-prone to error than
|
|
allocating data on the heap). In general, the variables are not intended
|
|
to pass information between different types of typemaps. However, this
|
|
can be done if you realize that local names have the argument number appended
|
|
to them. For example, you could do this:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%typemap(in) int *(int temp) {
|
|
temp = (int) PyInt_AsLong($input);
|
|
$1 = &temp;
|
|
}
|
|
|
|
%typemap(argout) int * {
|
|
PyObject *o = PyInt_FromLong(temp$argnum);
|
|
...
|
|
}
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
In this case, the <tt>$argnum</tt> variable is expanded into the argument
|
|
number. Therefore, the code will reference the appropriate local
|
|
such as <tt>temp1</tt> and <tt>temp2</tt>. It should be noted that there are
|
|
plenty of opportunities to break the universe here and that accessing locals
|
|
in this manner should probably be avoided. At the very least, you should make
|
|
sure that the typemaps sharing information have exactly the same types and names.
|
|
</p>
|
|
|
|
|
|
<H2><a name="Typemaps_nn51"></a>10.15 Where to go for more information?</H2>
|
|
|
|
|
|
<p>
|
|
The
|
|
best place to find out more information about writing typemaps is to
|
|
look in the SWIG library. Most language modules define all of their
|
|
default behavior using typemaps. These are found in files such as
|
|
<tt>python.swg</tt>, <tt>perl5.swg</tt>, <tt>tcl8.swg</tt> and so
|
|
forth. The <tt>typemaps.i</tt> file in the library also contains
|
|
numerous examples. You should look at these files to get a feel
|
|
for how to define typemaps of your own.
|
|
Some of the language modules support additional typemaps and further
|
|
information is available in the individual chapters for each target language.
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|