Consistent use of 'proxy' rather than 'shadow' throughout git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6211 626c5289-ae23-0410-ae9c-e8d60b6d4f22
675 lines
18 KiB
HTML
675 lines
18 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>Customization Features</title>
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="Customization"></a>11 Customization Features</H1>
|
|
<!-- INDEX -->
|
|
<ul>
|
|
<li><a href="#exception">Exception handling with %exception</a>
|
|
<ul>
|
|
<li><a href="#Customization_nn3">Handling exceptions in C code</a>
|
|
<li><a href="#Customization_nn4">Exception handling with longjmp()</a>
|
|
<li><a href="#Customization_nn5">Handling C++ exceptions</a>
|
|
<li><a href="#Customization_nn6">Defining different exception handlers</a>
|
|
<li><a href="#Customization_nn7">Using The SWIG exception library</a>
|
|
</ul>
|
|
<li><a href="#ownership">Object ownership and %newobject</a>
|
|
<li><a href="#features">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.
|
|
|
|
<H2><a name="exception"></a>11.1 Exception handling with %exception</H2>
|
|
|
|
|
|
<p>
|
|
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 either <tt>%exception</tt>
|
|
or <tt>%noexception</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.
|
|
</p>
|
|
|
|
<H3><a name="Customization_nn3"></a>11.1.1 Handling exceptions in C code</H3>
|
|
|
|
|
|
<p>
|
|
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>
|
|
|
|
<p>
|
|
To use these functions, functions simply call
|
|
<tt>throw_exception()</tt> to indicate an error occurred. For example
|
|
:</p>
|
|
|
|
<blockquote><pre>
|
|
double inv(double x) {
|
|
if (x != 0) return 1.0/x;
|
|
else {
|
|
throw_exception("Division by zero");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
To catch the exception, you can write a simple exception handler such
|
|
as the following (shown for Perl5) :</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.
|
|
</p>
|
|
|
|
<H3><a name="Customization_nn4"></a>11.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>
|
|
|
|
<p>
|
|
Now, within a C program, you can do the following :</p>
|
|
|
|
<blockquote><pre>
|
|
double inv(double x) {
|
|
if (x) return 1.0/x;
|
|
else throw(DivisionByZero);
|
|
}
|
|
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
Finally, to create a SWIG exception handler, write the following :</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.
|
|
|
|
<H3><a name="Customization_nn5"></a>11.1.3 Handling C++ exceptions</H3>
|
|
|
|
|
|
<p>
|
|
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>
|
|
|
|
<p>
|
|
The exception types need to be declared as classes elsewhere, possibly
|
|
in a header file :</p>
|
|
|
|
<blockquote><pre>
|
|
class RangeError {};
|
|
class DivisionByZero {};
|
|
class OutOfMemory {};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<H3><a name="Customization_nn6"></a>11.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> described in the section on
|
|
<a href="SWIGPlus.html#ambiguity_resolution_renaming">Ambiguity resolution and renaming</a>.
|
|
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:
|
|
</p>
|
|
|
|
<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>
|
|
|
|
<b>Compatibility note:</b> The <tt>%exception</tt> directive replaces
|
|
the functionality provided by the deprecated "except" typemap.
|
|
The typemap would allow exceptions to be thrown in the target
|
|
language based on the return type of a function 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.
|
|
|
|
<H3><a name="Customization_nn7"></a>11.1.5 Using The SWIG exception library</H3>
|
|
|
|
|
|
<p>
|
|
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>
|
|
|
|
<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>
|
|
|
|
<p>
|
|
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>
|
|
|
|
<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.
|
|
</p>
|
|
|
|
<H2><a name="ownership"></a>11.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:
|
|
</p>
|
|
|
|
<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 also 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:
|
|
</p>
|
|
|
|
<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:
|
|
</p>
|
|
|
|
<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:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
%newobject
|
|
char *strdup(const char *s);
|
|
</pre>
|
|
</blockquote>
|
|
The results might not be what you expect.
|
|
|
|
<H2><a name="features"></a>11.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>
|
|
|
|
<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:
|
|
</p>
|
|
|
|
<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:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/* Define a global exception handler */
|
|
%feature("except") {
|
|
try {
|
|
$action
|
|
}
|
|
...
|
|
}
|
|
|
|
... bunch of declarations ...
|
|
|
|
/* Disable the exception handler */
|
|
%feature("except");
|
|
</pre>
|
|
</blockquote>
|
|
|
|
The <tt>%feature</tt> directive can be used with different syntax.
|
|
The following are all equivalent:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
%feature("except") Object::method { $action };
|
|
%feature("except") Object::method %{ $action %};
|
|
%feature("except") Object::method " $action ";
|
|
%feature("except","$action") Object::method;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
The syntax in the first variation will generate the <tt>{ }</tt> delimeters used whereas the other variations will not.
|
|
The <tt>%feature</tt> directive also accepts XML style attributes in the same way that typemaps will.
|
|
Any number of attributes can be specified.
|
|
The following is the generic syntax for features:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
%feature("name","value", attribute1="AttibuteValue1") symbol;
|
|
%feature("name", attribute1="AttibuteValue1") symbol {value};
|
|
%feature("name", attribute1="AttibuteValue1") symbol %{value%};
|
|
%feature("name", attribute1="AttibuteValue1") symbol "value";
|
|
</pre>
|
|
</blockquote>
|
|
|
|
More than one attribute can be specified using a comma separated list.
|
|
The Java module is an example that uses attributes in <tt>%feature("except")</tt>.
|
|
The <tt>throws</tt> attribute specifies the name of a Java class to add to a proxy method's throws clause.
|
|
In the following example, <tt>MyExceptionClass</tt> is the name of the Java class for adding to the throws clause.
|
|
|
|
<blockquote>
|
|
<pre>
|
|
%feature("except", throws="MyExceptionClass") Object::method {
|
|
try {
|
|
$action
|
|
} catch (...) {
|
|
... code to throw a MyExceptionClass Java exception ...
|
|
}
|
|
};
|
|
</pre>
|
|
</blockquote>
|
|
|
|
Further details can be obtained from the <a href="Java.html#exception_handling">Java exception handling</a> section.
|
|
|
|
<p>
|
|
As can be seen, the intended use for the <tt>%feature</tt> directive is as a highly flexible customization mechanism that can be used to annotate
|
|
declarations with additional information for use by specific target language modules. Another example is
|
|
in the Python module. You might use <tt>%feature</tt> to rewrite proxy/shadow class code as follows:
|
|
</p>
|
|
|
|
<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>
|
|
|
|
Further details of <tt>%feature</tt> usage is described in the documentation for specific language modules.
|
|
|
|
</body>
|
|
</html>
|