The great merge
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4141 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
6fcc22a1f8
commit
516036631c
1508 changed files with 125983 additions and 44037 deletions
643
SWIG/Doc/Manual/Customization.html
Normal file
643
SWIG/Doc/Manual/Customization.html
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Customization Features</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
<a name="n1"></a><H1>9 Customization Features</H1>
|
||||
<!-- INDEX -->
|
||||
<ul>
|
||||
<li><a href="#n2">Exception handling with %exception</a>
|
||||
<ul>
|
||||
<li><a href="#n3">Handling exceptions in C code</a>
|
||||
<li><a href="#n4">Exception handling with longjmp()</a>
|
||||
<li><a href="#n5">Handling C++ exceptions</a>
|
||||
<li><a href="#n6">Defining different exception handlers</a>
|
||||
<li><a href="#n7">Applying exception handlers to specific datatypes.</a>
|
||||
<li><a href="#n8">Using The SWIG exception library</a>
|
||||
</ul>
|
||||
<li><a href="#n9">Object ownership and %newobject</a>
|
||||
<li><a href="#n10">Features and the %feature directive</a>
|
||||
</ul>
|
||||
<!-- INDEX -->
|
||||
|
||||
|
||||
|
||||
In many cases, it is desirable to change the default wrapping of
|
||||
particular declarations in an interface. For example, you might want
|
||||
to provide hooks for catching C++ exceptions, add assertions, or
|
||||
provide hints to the underlying code generator. This chapter
|
||||
describes some of these customization techniques. First, a discussion
|
||||
of exception handling is presented. Then, a more general-purpose
|
||||
customization mechanism known as "features" is described.
|
||||
|
||||
<a name="n2"></a><H2>9.1 Exception handling with %exception</H2>
|
||||
|
||||
|
||||
The <tt>%exception</tt> directive allows you to define a general purpose exception
|
||||
handler. For example, you can specify the following:
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%exception {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (RangeError) {
|
||||
PyErr_SetString(PyExc_IndexError,"index out-of-bounds");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
|
||||
When defined, the code enclosed in braces is inserted directly into the low-level wrapper
|
||||
functions. The special symbol <tt>$action</tt> gets replaced with the actual operation
|
||||
to be performed (a function call, method invocation, attribute access, etc.). An exception handler
|
||||
remains in effect until it is explicitly deleted. This is done by using <tt>%except</tt> with
|
||||
no code. For example:
|
||||
<p>
|
||||
<blockquote><pre>%exception; // Deletes any previously defined handler
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
<b>Compatibility note:</b> Previous versions of SWIG used a special directive <tt>%except</tt>
|
||||
for exception handling. That directive is still supported but is deprecated--<tt>%exception</tt>
|
||||
provides the same functionality, but is substantially more flexible.
|
||||
|
||||
<a name="n3"></a><H3>9.1.1 Handling exceptions in C code</H3>
|
||||
|
||||
|
||||
C has no formal exception handling mechanism so there are several approaches that might be
|
||||
used. A somewhat common technique is to simply set a special error code. For example:
|
||||
|
||||
<p>
|
||||
<blockquote><pre>
|
||||
|
||||
/* File : except.c */
|
||||
|
||||
static char error_message[256];
|
||||
static int error_status = 0;
|
||||
|
||||
void throw_exception(char *msg) {
|
||||
strncpy(error_message,msg,256);
|
||||
error_status = 1;
|
||||
}
|
||||
|
||||
void clear_exception() {
|
||||
error_status = 0;
|
||||
}
|
||||
char *check_exception() {
|
||||
if (error_status) return error_message;
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
To use these functions, functions simply call
|
||||
<tt>throw_exception()</tt> to indicate an error occurred. For example
|
||||
:<p>
|
||||
<p>
|
||||
<blockquote><pre>double inv(double x) {
|
||||
if (x != 0) return 1.0/x;
|
||||
else {
|
||||
throw_exception("Division by zero");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
To catch the exception, you can write a simple exception handler such
|
||||
as the following (shown for Perl5) :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%exception {
|
||||
char *err;
|
||||
clear_exception();
|
||||
$action
|
||||
if ((err = check_exception())) {
|
||||
croak(err);
|
||||
}
|
||||
}
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
In this case, when an error occurs, it is translated into a Perl error.
|
||||
|
||||
<a name="n4"></a><H3>9.1.2 Exception handling with longjmp()</H3>
|
||||
|
||||
|
||||
Exception handling can also be added to C code using the
|
||||
<tt><setjmp.h></tt> library. Here is a minimalistic implementation that
|
||||
relies on the C preprocessor :
|
||||
|
||||
<blockquote><pre>
|
||||
/* File : except.c
|
||||
Just the declaration of a few global variables we're going to use */
|
||||
|
||||
#include <setjmp.h>
|
||||
jmp_buf exception_buffer;
|
||||
int exception_status;
|
||||
|
||||
/* File : except.h */
|
||||
#include <setjmp.h>
|
||||
extern jmp_buf exception_buffer;
|
||||
extern int exception_status;
|
||||
|
||||
#define try if ((exception_status = setjmp(exception_buffer)) == 0)
|
||||
#define catch(val) else if (exception_status == val)
|
||||
#define throw(val) longjmp(exception_buffer,val)
|
||||
#define finally else
|
||||
|
||||
/* Exception codes */
|
||||
|
||||
#define RangeError 1
|
||||
#define DivisionByZero 2
|
||||
#define OutOfMemory 3
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
Now, within a C program, you can do the following :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>double inv(double x) {
|
||||
if (x) return 1.0/x;
|
||||
else throw(DivisionByZero);
|
||||
}
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
Finally, to create a SWIG exception handler, write the following :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%{
|
||||
#include "except.h"
|
||||
%}
|
||||
|
||||
%exception {
|
||||
try {
|
||||
$action
|
||||
} catch(RangeError) {
|
||||
croak("Range Error");
|
||||
} catch(DivisionByZero) {
|
||||
croak("Division by zero");
|
||||
} catch(OutOfMemory) {
|
||||
croak("Out of memory");
|
||||
} finally {
|
||||
croak("Unknown exception");
|
||||
}
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
Note: This implementation is only intended to illustrate the general idea. To make it work better, you'll need to
|
||||
modify it to handle nested <tt>try</tt> declarations.
|
||||
|
||||
<a name="n5"></a><H3>9.1.3 Handling C++ exceptions</H3>
|
||||
|
||||
|
||||
Handling C++ exceptions is also straightforward. For example:
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%exception {
|
||||
try {
|
||||
$action
|
||||
} catch(RangeError) {
|
||||
croak("Range Error");
|
||||
} catch(DivisionByZero) {
|
||||
croak("Division by zero");
|
||||
} catch(OutOfMemory) {
|
||||
croak("Out of memory");
|
||||
} catch(...) {
|
||||
croak("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
The exception types need to be declared as classes elsewhere, possibly
|
||||
in a header file :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>class RangeError {};
|
||||
class DivisionByZero {};
|
||||
class OutOfMemory {};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<a name="n6"></a><H3>9.1.4 Defining different exception handlers</H3>
|
||||
|
||||
|
||||
By default, the <tt>%exception</tt> directive creates an exception
|
||||
handler that is used for all wrapper functions that follow it. Unless
|
||||
there is a well-defined (and simple) error handling mechanism in place,
|
||||
defining one universal exception handler may be unwieldy and result
|
||||
in excessive code bloat since the handler is inlined into each wrapper function.
|
||||
<p>
|
||||
|
||||
To fix this, you can be more selective about how you use the
|
||||
<tt>%exception</tt> directive. One approach is to only place it around
|
||||
critical pieces of code. For example:
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%exception {
|
||||
... your exception handler ...
|
||||
}
|
||||
/* Define critical operations that can throw exceptions here */
|
||||
|
||||
%exception;
|
||||
|
||||
/* Define non-critical operations that don't throw exceptions */
|
||||
</pre></blockquote>
|
||||
|
||||
More precise control over exception handling can be obtained by attaching an exception handler
|
||||
to specific declaration name. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%exception allocate {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (MemoryError) {
|
||||
croak("Out of memory");
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this case, the exception handler is only attached to declarations
|
||||
named "allocate". This would include both global and member
|
||||
functions. The names supplied to <tt>%exception</tt> follow the same
|
||||
rules as for <tt>%rename</tt>. For example, if you wanted to define
|
||||
an exception handler for a specific class, you might write this:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%exception Object::allocate {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (MemoryError) {
|
||||
croak("Out of memory");
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
When a class prefix is supplied, the exception handler is applied to the corresponding declaration
|
||||
in the specified class as well as for identically named functions appearing in derived classes.
|
||||
|
||||
<p>
|
||||
<tt>%exception</tt> can even be used to pinpoint a precise declaration when overloading is used. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%exception Object::allocate(int) {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (MemoryError) {
|
||||
croak("Out of memory");
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
Attaching exceptions to specific declarations is a good way to reduce code bloat. It can also be a useful way
|
||||
to attach exceptions to specific parts of a header file. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%module example
|
||||
%{
|
||||
#include "someheader.h"
|
||||
%}
|
||||
|
||||
// Define a few exception handlers for specific declarations
|
||||
%exception Object::allocate(int) {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (MemoryError) {
|
||||
croak("Out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
%exception Object::getitem {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (RangeError) {
|
||||
croak("Index out of range");
|
||||
}
|
||||
}
|
||||
...
|
||||
// Read a raw header file
|
||||
%include "someheader.h"
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<a name="n7"></a><H3>9.1.5 Applying exception handlers to specific datatypes.</H3>
|
||||
|
||||
|
||||
An alternative approach to using the <tt>%exception</tt> directive is to
|
||||
use the "except" typemap. This allows you to attach an error handler
|
||||
to specific datatypes and function name. The typemap is applied to
|
||||
the return value of a function. For example :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>%typemap(except) void *malloc {
|
||||
$action
|
||||
if (!$1) {
|
||||
PyExc_SetString(PyExc_MemoryError,"Out of memory in $symname");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *malloc(int size);
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
When applied, this automatically checks the return value of
|
||||
<tt>malloc()</tt> and raises an exception if it's invalid. For example
|
||||
:<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>
|
||||
>>> from example import *
|
||||
>>> a = malloc(2048)
|
||||
>>> b = malloc(1500000000)
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
MemoryError: Out of memory in malloc
|
||||
>>>
|
||||
</pre></blockquote>
|
||||
|
||||
When "except" typemaps are used, they override any exception handler defined with
|
||||
<tt>%exception</tt>.<p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility note:</b> The except typemap dates to earlier SWIG
|
||||
releases and was intended to be a mechanism for pinpointing specific
|
||||
declarations. However, it never really worked that well and the new
|
||||
%exception directive is much better. The except typemap is preserved for now, but
|
||||
may be deprecated in future versions.
|
||||
|
||||
<a name="n8"></a><H3>9.1.6 Using The SWIG exception library</H3>
|
||||
|
||||
|
||||
The <tt>exception.i</tt> library file provides support for creating
|
||||
language independent exceptions in your interfaces. To use it, simply
|
||||
put an "<tt>%include exception.i</tt>" in your interface file. This
|
||||
creates a function<tt> SWIG_exception()</tt> that can be used to raise
|
||||
common scripting language exceptions in a portable manner. For example :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>// Language independent exception handler
|
||||
%include exception.i
|
||||
|
||||
%exception {
|
||||
try {
|
||||
$action
|
||||
} catch(RangeError) {
|
||||
SWIG_exception(SWIG_ValueError, "Range Error");
|
||||
} catch(DivisionByZero) {
|
||||
SWIG_exception(SWIG_DivisionByZero, "Division by zero");
|
||||
} catch(OutOfMemory) {
|
||||
SWIG_exception(SWIG_MemoryError, "Out of memory");
|
||||
} catch(...) {
|
||||
SWIG_exception(SWIG_RuntimeError,"Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
As arguments, <tt>SWIG_exception()</tt> takes an error type code (an
|
||||
integer) and an error message string. The currently supported error
|
||||
types are :<p>
|
||||
|
||||
<p>
|
||||
<blockquote><pre>SWIG_MemoryError
|
||||
SWIG_IOError
|
||||
SWIG_RuntimeError
|
||||
SWIG_IndexError
|
||||
SWIG_TypeError
|
||||
SWIG_DivisionByZero
|
||||
SWIG_OverflowError
|
||||
SWIG_SyntaxError
|
||||
SWIG_ValueError
|
||||
SWIG_SystemError
|
||||
SWIG_UnknownError
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
|
||||
Since the <tt>SWIG_exception()</tt> function is defined at the C-level
|
||||
it can be used elsewhere in SWIG. This includes typemaps and helper
|
||||
functions.
|
||||
|
||||
<a name="n9"></a><H2>9.2 Object ownership and %newobject</H2>
|
||||
|
||||
|
||||
A common problem in some applications is managing proper ownership of objects. For
|
||||
example, consider a function like this:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
Foo *blah() {
|
||||
Foo *f = new Foo();
|
||||
return f;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
If you wrap the function <tt>blah()</tt>, SWIG has no idea that the
|
||||
return value is a newly allocated object. As a result, the resulting
|
||||
extension module may produce a memory leak (SWIG is conservative and
|
||||
will never delete objects unless it knows for certain that the
|
||||
returned object was newly created).
|
||||
|
||||
<p>
|
||||
To fix this, you can provide an extra hint to the code generator using
|
||||
the <tt>%newobject</tt> directive. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%newobject blah;
|
||||
Foo *blah();
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<tt>%newobject</tt> works exactly like <tt>%rename</tt> and <tt>%exception</tt>. In other words,
|
||||
you can attach it to class members and parameterized declarations as before. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%newobject ::blah(); // Only applies to global blah
|
||||
%newobject Object::blah(int,double); // Only blah(int,double) in Object
|
||||
%newobject *::copy; // Copy method in all classes
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
When <tt>%newobject</tt> is supplied, many language modules will
|
||||
arrange to take ownership of the return value. This allows the value
|
||||
to be automatically garbage-collected when it is no longer in use. However,
|
||||
this depends entirely on the target language (a language module may choose to ignore
|
||||
the <tt>%newobject</tt> directive).
|
||||
|
||||
<p>
|
||||
Closely related to <tt>%newobject</tt> is a special typemap. The "newfree" typemap
|
||||
can be used to deallocate a newly allocated return value. It is only available on
|
||||
methods for which <tt>%newobject</tt> has been applied and is commonly used to clean-up string
|
||||
results. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%typemap(newfree) char * "free($1);";
|
||||
...
|
||||
%newobject strdup;
|
||||
...
|
||||
char *strdup(const char *s);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this case, the result of the function is a string in the target language. Since this string
|
||||
is a copy of the original result, the data returned by <tt>strdup()</tt> is no longer needed.
|
||||
The "newfree" typemap in the example simply releases this memory.
|
||||
|
||||
<p>
|
||||
<b>Compatibility note:</b> Previous versions of SWIG had a special <tt>%new</tt> directive. However, unlike <tt>%newobject</tt>,
|
||||
it only applied to the next declaration. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%new char *strdup(const char *s);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
For now this is still supported but is deprecated.
|
||||
|
||||
<p>
|
||||
<b>How to shoot yourself in the foot:</b> The <tt>%newobject</tt> directive is not a declaration modifier like the old
|
||||
<tt>%new</tt> directive. Don't write code like this:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%newobject
|
||||
char *strdup(const char *s);
|
||||
</pre>
|
||||
</blockquote>
|
||||
The results might not be what you expect.
|
||||
|
||||
<a name="n10"></a><H2>9.3 Features and the %feature directive</H2>
|
||||
|
||||
|
||||
Both <tt>%exception</tt> and <tt>%newobject</tt> are examples of a
|
||||
more general purpose customization mechanism known as "features." A
|
||||
feature is simply a user-definable property that is attached to
|
||||
specific declarations in an interface file. Features are attached
|
||||
using the <tt>%feature</tt> directive. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%feature("except") Object::allocate {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
catch (MemoryError) {
|
||||
croak("Out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
%feature("new","1") *::copy;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In fact, the <tt>%exception</tt> and <tt>%newobject</tt> directives are really nothing more than macros
|
||||
involving <tt>%feature</tt>:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#define %exception %feature("except")
|
||||
#define %newobject %feature("new","1")
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
The <tt>%feature</tt> directive follows the same name matching rules
|
||||
as the <tt>%rename</tt> directive (which is in fact just a special
|
||||
form of <tt>%feature</tt>). This means that features can be applied with
|
||||
pinpoint accuracy to specific declarations if needed.
|
||||
|
||||
<p>
|
||||
When a feature is defined, it is given a name and a value. Most commonly, the
|
||||
value is supplied after the declaration name as shown for the <tt>"except"</tt>
|
||||
example above. However, if the feature is simple, a value might be supplied
|
||||
as an extra argument as shown for the <tt>"new"</tt> feature.
|
||||
|
||||
<p>
|
||||
A feature stays in effect until it is explicitly disabled. A feature is disabled by
|
||||
supplying a <tt>%feature</tt> directive with no value. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%feature("except") Object::allocate; // Removes any previously defined feature
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
If no declaration name is given, a global feature is defined. This feature is then
|
||||
attached to <em>every</em> declaration that follows. This is how global exception handlers
|
||||
are defined. For example:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/* Define a global exception handler */
|
||||
%feature("except") {
|
||||
try {
|
||||
$action
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
... bunch of declarations ...
|
||||
|
||||
/* Disable the exception handler */
|
||||
%feature("except");
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<tt>%feature</tt> is a relatively new addition to SWIG that was not added until version 1.3.10.
|
||||
Its intended use is as a highly flexible customization mechanism that can be used to annotate
|
||||
declarations with additional information for use by specific target language modules. For example,
|
||||
in the Python module, you might use <tt>%feature</tt> to rewrite shadow class code as follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
%module example
|
||||
%rename(bar_id) bar(int,double);
|
||||
|
||||
// Rewrite bar() to allow some nice overloading
|
||||
|
||||
%feature("shadow") Foo::bar(int) %{
|
||||
def bar(*args):
|
||||
if len(args) == 3:
|
||||
return apply(examplec.Foo_bar_id,args)
|
||||
return apply(examplec.Foo_bar,args)
|
||||
%}
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
int bar(int x);
|
||||
int bar(int x, double y);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
As of this writing, <tt>%feature</tt> is still experimental. Further details of its
|
||||
use will be described in the documentation for specific language modules.
|
||||
|
||||
<p><hr>
|
||||
|
||||
<address>SWIG 1.3 - Last Modified : December 9, 2001</address>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue