diff options
Diffstat (limited to 'Doc/Manual/Arguments.html')
| -rw-r--r-- | Doc/Manual/Arguments.html | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/Doc/Manual/Arguments.html b/Doc/Manual/Arguments.html new file mode 100644 index 0000000..8ab51fa --- /dev/null +++ b/Doc/Manual/Arguments.html @@ -0,0 +1,496 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>Argument Handling</title> +<link rel="stylesheet" type="text/css" href="style.css"> +</head> + +<body bgcolor="#ffffff"> +<H1><a name="Arguments"></a>9 Argument Handling</H1> +<!-- INDEX --> +<div class="sectiontoc"> +<ul> +<li><a href="#Arguments_nn2">The typemaps.i library</a> +<ul> +<li><a href="#Arguments_nn3">Introduction</a> +<li><a href="#Arguments_nn4">Input parameters</a> +<li><a href="#Arguments_nn5">Output parameters</a> +<li><a href="#Arguments_nn6">Input/Output parameters</a> +<li><a href="#Arguments_nn7">Using different names</a> +</ul> +<li><a href="#Arguments_nn8">Applying constraints to input values</a> +<ul> +<li><a href="#Arguments_nn9">Simple constraint example</a> +<li><a href="#Arguments_nn10">Constraint methods</a> +<li><a href="#Arguments_nn11">Applying constraints to new datatypes</a> +</ul> +</ul> +</div> +<!-- INDEX --> + + + +<p> +In Chapter 3, SWIG's treatment of basic datatypes and pointers was +described. In particular, primitive types such as <tt>int</tt> and +<tt>double</tt> are mapped to corresponding types in the target +language. For everything else, pointers are used to refer to +structures, classes, arrays, and other user-defined datatypes. +However, in certain applications it is desirable to change SWIG's +handling of a specific datatype. For example, you might want to +return multiple values through the arguments of a function. This chapter +describes some of the techniques for doing this. +</p> + +<H2><a name="Arguments_nn2"></a>9.1 The typemaps.i library</H2> + + +<p> +This section describes the <tt>typemaps.i</tt> library file--commonly used to +change certain properties of argument conversion. +</p> + +<H3><a name="Arguments_nn3"></a>9.1.1 Introduction</H3> + + +<p> +Suppose you had a C function like this: +</p> + +<div class="code"><pre> +void add(double a, double b, double *result) { + *result = a + b; +} +</pre></div> + +<p> +From reading the source code, it is clear that the function is storing +a value in the <tt>double *result</tt> parameter. However, since SWIG +does not examine function bodies, it has no way to know that this is +the underlying behavior. +</p> + +<p> +One way to deal with this is to use the +<tt>typemaps.i</tt> library file and write interface code like this: +</p> + +<div class="code"><pre> +// Simple example using typemaps +%module example +%include "typemaps.i" + +%apply double *OUTPUT { double *result }; +%inlne %{ +extern void add(double a, double b, double *result); +%} +</pre></div> + +<p> +The <tt>%apply</tt> directive tells SWIG that you are going to apply +a special type handling rule to a type. The "<tt>double *OUTPUT</tt>" specification is the +name of a rule that defines how to return an output value from an argument of type +<tt>double *</tt>. This rule gets applied to all of the datatypes +listed in curly braces-- in this case "<tt>double *result</tt>".</p> + +<p> +When the resulting module is created, you can now use the function +like this (shown for Python): +</p> + +<div class="targetlang"><pre> +>>> a = add(3,4) +>>> print a +7 +>>> +</pre></div> + +<p> +In this case, you can see how the output value normally returned in +the third argument has magically been transformed into a function +return value. Clearly this makes the function much easier to use +since it is no longer necessary to manufacture a special <tt>double +*</tt> object and pass it to the function somehow. +</p> + +<p> +Once a typemap has been applied to a type, it stays in effect for all future occurrences +of the type and name. For example, you could write the following: +</p> + +<div class="code"><pre> +%module example +%include "typemaps.i" + +%apply double *OUTPUT { double *result }; + +%inline %{ +extern void add(double a, double b, double *result); +extern void sub(double a, double b, double *result); +extern void mul(double a, double b, double *result); +extern void div(double a, double b, double *result); +%} +... +</pre></div> + +<p> +In this case, the <tt>double *OUTPUT</tt> rule is applied to all of the functions that follow. +</p> + +<p> +Typemap transformations can even be extended to multiple return values. +For example, consider this code: +</p> + +<div class="code"> +<pre> +%include "typemaps.i" +%apply int *OUTPUT { int *width, int *height }; + +// Returns a pair (width,height) +void getwinsize(int winid, int *width, int *height); +</pre> +</div> + +<p> +In this case, the function returns multiple values, allowing it to be used like this: +</p> + +<div class="targetlang"><pre> +>>> w,h = genwinsize(wid) +>>> print w +400 +>>> print h +300 +>>> +</pre> +</div> + +<p> +It should also be noted that although the <tt>%apply</tt> directive is +used to associate typemap rules to datatypes, you can also use the +rule names directly in arguments. For example, you could write this: +</p> + +<div class="code"><pre> +// Simple example using typemaps +%module example +%include "typemaps.i" + +%{ +extern void add(double a, double b, double *OUTPUT); +%} +extern void add(double a, double b, double *OUTPUT); +</pre></div> + +<p> +Typemaps stay in effect until they are explicitly deleted or redefined to something +else. To clear a typemap, the <tt>%clear</tt> directive should be used. For example: +</p> + +<div class="code"> +<pre> +%clear double *result; // Remove all typemaps for double *result +</pre> +</div> + +<H3><a name="Arguments_nn4"></a>9.1.2 Input parameters</H3> + + +<p> +The following typemaps instruct SWIG that a pointer really only holds a single +input value: +</p> + +<div class="code"><pre> +int *INPUT +short *INPUT +long *INPUT +unsigned int *INPUT +unsigned short *INPUT +unsigned long *INPUT +double *INPUT +float *INPUT +</pre></div> + +<p> +When used, it allows values to be passed instead of pointers. For example, consider this +function: +</p> + +<div class="code"><pre> +double add(double *a, double *b) { + return *a+*b; +} +</pre></div> + +<p> +Now, consider this SWIG interface: +</p> + +<div class="code"><pre> +%module example +%include "typemaps.i" +... +%{ +extern double add(double *, double *); +%} +extern double add(double *INPUT, double *INPUT); + +</pre></div> + +<p> +When the function is used in the scripting language interpreter, it will work like this: +</p> + +<div class="targetlang"><pre> +result = add(3,4) +</pre></div> + +<H3><a name="Arguments_nn5"></a>9.1.3 Output parameters</H3> + + +<p> +The following typemap rules tell SWIG that pointer is the output value of a +function. When used, you do not need to supply the argument when +calling the function. Instead, one or more output values are returned. +</p> + +<div class="code"><pre> +int *OUTPUT +short *OUTPUT +long *OUTPUT +unsigned int *OUTPUT +unsigned short *OUTPUT +unsigned long *OUTPUT +double *OUTPUT +float *OUTPUT + +</pre></div> +<p> +These methods can be used as shown in an earlier example. For example, if you have this C function :</p> + +<div class="code"><pre> +void add(double a, double b, double *c) { + *c = a+b; +} +</pre></div> + +<p> +A SWIG interface file might look like this :</p> + +<div class="code"><pre> +%module example +%include "typemaps.i" +... +%inline %{ +extern void add(double a, double b, double *OUTPUT); +%} + +</pre></div> + +<p> +In this case, only a single output value is returned, but this is not +a restriction. An arbitrary number of output values can be returned by applying +the output rules to more than one argument (as shown previously). +</p> + +<p> +If the function also returns a value, it is returned along with the argument. For example, +if you had this: +</p> + +<div class="code"><pre> +extern int foo(double a, double b, double *OUTPUT); +</pre></div> + +<p> +The function will return two values like this: +</p> + +<div class="targetlang"> +<pre> +iresult, dresult = foo(3.5, 2) +</pre> +</div> + +<H3><a name="Arguments_nn6"></a>9.1.4 Input/Output parameters</H3> + + +<p> +When a pointer serves as both an input and output value you can use +the following typemaps :</p> + +<div class="code"><pre> +int *INOUT +short *INOUT +long *INOUT +unsigned int *INOUT +unsigned short *INOUT +unsigned long *INOUT +double *INOUT +float *INOUT + +</pre></div> + +<p> +A C function that uses this might be something like this:</p> + +<div class="code"><pre> +void negate(double *x) { + *x = -(*x); +} + +</pre></div> + +<p> +To make x function as both and input and output value, declare the +function like this in an interface file :</p> + +<div class="code"><pre> +%module example +%include "typemaps.i" +... +%{ +extern void negate(double *); +%} +extern void negate(double *INOUT); + +</pre></div> + +<p> +Now within a script, you can simply call the function normally :</p> + +<div class="targetlang"><pre> +a = negate(3); # a = -3 after calling this +</pre></div> + +<p> +One subtle point of the <tt>INOUT</tt> rule is that many scripting languages +enforce mutability constraints on primitive objects (meaning that simple objects +like integers and strings aren't supposed to change). Because of this, you can't +just modify the object's value in place as the underlying C function does in this example. +Therefore, the <tt>INOUT</tt> rule returns the modified value as a new object +rather than directly overwriting the value of the original input object. +</p> + +<p> +<b>Compatibility note :</b> The <tt>INOUT</tt> rule used to be known as <tt>BOTH</tt> in earlier versions of +SWIG. Backwards compatibility is preserved, but deprecated. +</p> + +<H3><a name="Arguments_nn7"></a>9.1.5 Using different names</H3> + + +<p> +As previously shown, the <tt>%apply</tt> directive can be used to apply the <tt>INPUT</tt>, <tt>OUTPUT</tt>, and +<tt>INOUT</tt> typemaps to different argument names. For example: +</p> + +<div class="code"><pre> +// Make double *result an output value +%apply double *OUTPUT { double *result }; + +// Make Int32 *in an input value +%apply int *INPUT { Int32 *in }; + +// Make long *x inout +%apply long *INOUT {long *x}; + +</pre></div> + +<p> +To clear a rule, the <tt>%clear</tt> directive is used: +</p> + +<div class="code"><pre> +%clear double *result; +%clear Int32 *in, long *x; +</pre></div> + +<p> +Typemap declarations are lexically scoped so a typemap takes effect from the point of definition to the end of the +file or a matching <tt>%clear</tt> declaration. +</p> + +<H2><a name="Arguments_nn8"></a>9.2 Applying constraints to input values</H2> + + +<p> +In addition to changing the handling of various input values, it is +also possible to use typemaps to apply constraints. For example, maybe you want to +insure that a value is positive, or that a pointer is non-NULL. This +can be accomplished including the <tt>constraints.i</tt> library file. +</p> + +<H3><a name="Arguments_nn9"></a>9.2.1 Simple constraint example</H3> + + +<p> +The constraints library is best illustrated by the following interface +file :</p> + +<div class="code"><pre> +// Interface file with constraints +%module example +%include "constraints.i" + +double exp(double x); +double log(double POSITIVE); // Allow only positive values +double sqrt(double NONNEGATIVE); // Non-negative values only +double inv(double NONZERO); // Non-zero values +void free(void *NONNULL); // Non-NULL pointers only + +</pre></div> + +<p> +The behavior of this file is exactly as you would expect. If any of +the arguments violate the constraint condition, a scripting language +exception will be raised. As a result, it is possible to catch bad +values, prevent mysterious program crashes and so on.</p> + +<H3><a name="Arguments_nn10"></a>9.2.2 Constraint methods</H3> + + +<p> +The following constraints are currently available</p> + +<div class="code"><pre> +POSITIVE Any number > 0 (not zero) +NEGATIVE Any number < 0 (not zero) +NONNEGATIVE Any number >= 0 +NONPOSITIVE Any number <= 0 +NONZERO Nonzero number +NONNULL Non-NULL pointer (pointers only). + +</pre></div> + +<H3><a name="Arguments_nn11"></a>9.2.3 Applying constraints to new datatypes</H3> + + +<p> +The constraints library only supports the primitive C datatypes, but it +is easy to apply it to new datatypes using <tt>%apply</tt>. For +example :</p> + +<div class="code"><pre> +// Apply a constraint to a Real variable +%apply Number POSITIVE { Real in }; + +// Apply a constraint to a pointer type +%apply Pointer NONNULL { Vector * }; + +</pre></div> + +<p> +The special types of "Number" and "Pointer" can be applied to any +numeric and pointer variable type respectively. To later remove a +constraint, the <tt>%clear</tt> directive can be used :</p> + +<div class="code"><pre> +%clear Real in; +%clear Vector *; +</pre></div> + +</body> +</html> |
