mirror of https://github.com/swig/swig
942 lines
25 KiB
HTML
942 lines
25 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and Modula-3</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
</head>
|
|
<body bgcolor="#FFFFFF">
|
|
<H1><a name="Modula3"></a>27 SWIG and Modula-3</H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Modula3_modula3_overview">Overview</a>
|
|
<ul>
|
|
<li><a href="#Modula3_motivation">Motivation</a>
|
|
</ul>
|
|
<li><a href="#Modula3_conception">Conception</a>
|
|
<ul>
|
|
<li><a href="#Modula3_cinterface">Interfaces to C libraries</a>
|
|
<li><a href="#Modula3_cppinterface">Interfaces to C++ libraries</a>
|
|
</ul>
|
|
<li><a href="#Modula3_preliminaries">Preliminaries</a>
|
|
<ul>
|
|
<li><a href="#Modula3_compilers">Compilers</a>
|
|
<li><a href="#Modula3_commandline">Additional Commandline Options</a>
|
|
</ul>
|
|
<li><a href="#Modula3_typemaps">Modula-3 typemaps</a>
|
|
<ul>
|
|
<li><a href="#Modula3_inoutparam">Inputs and outputs</a>
|
|
<li><a href="#Modula3_ordinals">Subranges, Enumerations, Sets</a>
|
|
<li><a href="#Modula3_class">Objects</a>
|
|
<li><a href="#Modula3_imports">Imports</a>
|
|
<li><a href="#Modula3_exceptions">Exceptions</a>
|
|
<li><a href="#Modula3_typemap_example">Example</a>
|
|
</ul>
|
|
<li><a href="#Modula3_hints">More hints to the generator</a>
|
|
<ul>
|
|
<li><a href="#Modula3_features">Features</a>
|
|
<li><a href="#Modula3_pragmas">Pragmas</a>
|
|
</ul>
|
|
<li><a href="#Modula3_remarks">Remarks</a>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
This chapter describes SWIG's support for
|
|
<a href="http://modula3.org/">Modula-3</a>.
|
|
You should be familiar with the
|
|
<a href="SWIG.html#SWIG">basics</a>
|
|
of SWIG,
|
|
especially
|
|
<a href="Typemaps.html#Typemaps">typemaps</a>.
|
|
</p>
|
|
|
|
<H2><a name="Modula3_modula3_overview"></a>27.1 Overview</H2>
|
|
|
|
|
|
<p>
|
|
Modula-3 is a compiled language in the tradition of Niklaus Wirth's Modula 2,
|
|
which is in turn a successor to Pascal.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG's Modula-3 support is currently very basic and highly experimental!
|
|
Many features are still not designed satisfyingly
|
|
and I need more discussion about the odds and ends.
|
|
Don't rely on any feature, incompatible changes are likely in the future!
|
|
However, the Modula-3 generator was already useful for interfacing
|
|
to the libraries:
|
|
</p>
|
|
|
|
<ol>
|
|
<li>
|
|
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/plplot/">
|
|
PLPlot
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/fftw/">
|
|
FFTW
|
|
</a>
|
|
</li>
|
|
</ol>
|
|
|
|
<H3><a name="Modula3_motivation"></a>27.1.1 Motivation</H3>
|
|
|
|
|
|
<p>
|
|
Although it is possible to write Modula-3 code that performs as well as C/C++
|
|
most existing libraries are not written in Modula-3 but in C or C++, and
|
|
even libraries in other languages may provide C header files.
|
|
</p>
|
|
|
|
<p>
|
|
Fortunately Modula-3 can call C functions, but you have to write Modula-3
|
|
interfaces to them, and to make things comfortable you will also need
|
|
wrappers that convert between high-level features of Modula-3 (garbage
|
|
collecting, exceptions) and the explicit tracking of allocated memory and
|
|
exception codes used by C APIs.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG converts C headers to Modula-3 interfaces for you, and using typemaps
|
|
you can pass <tt>TEXT</tt>s or open arrays, and convert error return codes
|
|
into exceptions.
|
|
</p>
|
|
|
|
<p>
|
|
If the library API is ill designed
|
|
writing appropriate typemaps can still be time-consuming.
|
|
E.g. C programmers are very creative to work-around
|
|
missing data types like (real) enumerations and sets.
|
|
You should turn such work-arounds back to the Modula-3 way
|
|
otherwise you lose static safety and consistency.
|
|
</p>
|
|
|
|
<p>
|
|
Without SWIG you would probably never consider trying to call C++ libraries
|
|
from Modula-3, but with SWIG this is becomes feasible.
|
|
SWIG can generate C wrappers to C++ functions and object methods
|
|
that may throw exceptions, and then wrap these C wrappers for Modula-3.
|
|
To make it complete you can then hide the C interface with Modula-3 classes and
|
|
exceptions.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG allows you to call C and C++ libraries from Modula-3 (even with call back
|
|
functions), but it doesn't allow you to easily integrate a Modula-3 module into
|
|
a C/C++ project.
|
|
</p>
|
|
|
|
<H2><a name="Modula3_conception"></a>27.2 Conception</H2>
|
|
|
|
|
|
<H3><a name="Modula3_cinterface"></a>27.2.1 Interfaces to C libraries</H3>
|
|
|
|
|
|
<p>
|
|
Modula-3 has integrated support for calling C functions.
|
|
This is also extensively used by the standard Modula-3 libraries
|
|
to call OS functions.
|
|
The Modula-3 part of SWIG and the corresponding SWIG library
|
|
modula3.swg
|
|
contain code that uses these features.
|
|
Because of the built-in support there is no need
|
|
for calling the SWIG kernel to generate wrappers written in C.
|
|
All conversion and argument checking can be done in Modula-3
|
|
and the interfacing is quite efficient.
|
|
All you have to do is to write pieces of Modula-3 code
|
|
that SWIG puts together.
|
|
</p>
|
|
|
|
<table border summary="Modula-3 C library support">
|
|
<tr><th colspan=2>C library support integrated in Modula-3<th></tr>
|
|
<tr>
|
|
<td>Pragma <tt><* EXTERNAL *></tt></td>
|
|
<td>Precedes a declaration of a PROCEDURE that is implemented
|
|
in an external library instead of a Modula-3 module.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Pragma <tt><* CALLBACK *></tt></td>
|
|
<td>Precedes a declaration of a PROCEDURE that should be called
|
|
by external library code.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Module <tt>Ctypes</tt></td>
|
|
<td>Contains Modula-3 types that match some basic C types.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Module <tt>M3toC</tt></td>
|
|
<td>Contains routines that convert between Modula-3's <tt>TEXT</tt> type
|
|
and C's <tt>char *</tt> type.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>
|
|
In each run of SWIG the Modula-3 part
|
|
generates several files:
|
|
</p>
|
|
<table border summary="Modula-3 generated files">
|
|
<tr>
|
|
<th>Module name scheme</th>
|
|
<th>Identifier for <tt>%insert</tt></th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Module<tt>Raw.i3</tt></td>
|
|
<td><tt>m3rawintf</tt></td>
|
|
<td>Declaration of types that are equivalent to those of the C library,
|
|
<tt>EXTERNAL</tt> procedures as interface to the C library functions</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Module<tt>Raw.m3</tt></td>
|
|
<td><tt>m3rawimpl</tt></td>
|
|
<td>Almost empty.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Module<tt>.i3</tt></td>
|
|
<td><tt>m3wrapintf</tt></td>
|
|
<td>Declaration of comfortable wrappers to the C library functions.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Module<tt>.m3</tt></td>
|
|
<td><tt>m3wrapimpl</tt></td>
|
|
<td>Implementation of the wrappers that
|
|
convert between Modula-3 and C types,
|
|
check for validity of values,
|
|
hand-over resource management to the garbage collector using <tt>WeakRef</tt>s
|
|
and raises exceptions.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><tt>m3makefile</tt></td>
|
|
<td><tt>m3makefile</tt></td>
|
|
<td>Add the modules above to the Modula-3 project and
|
|
specify the name of the Modula-3 wrapper library
|
|
to be generated.
|
|
|
|
Today I'm not sure if it is a good idea
|
|
to create a <tt>m3makefile</tt> in each run,
|
|
because SWIG must be started for each Modula-3 module it creates.
|
|
Thus the m3makefile is overwritten each time. :-(
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>
|
|
Here's a scheme of how the function calls to Modula-3 wrappers
|
|
are redirected to C library functions:
|
|
</p>
|
|
|
|
<table summary="Modula-3 C library">
|
|
<tr>
|
|
<td align=center>
|
|
Modula-3 wrapper<br>
|
|
Module<tt>.i3</tt><br>
|
|
generated by Modula-3 part of SWIG
|
|
</td>
|
|
<td></td>
|
|
<td align=center></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=center>
|
|
<!-- pre tag overrides centering -->
|
|
|<br>
|
|
v
|
|
</td>
|
|
<td></td>
|
|
<td align=center></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=center>
|
|
Modula-3 interface to C<br>
|
|
Module<tt>Raw.i3</tt><br>
|
|
generated by Modula-3 part of SWIG
|
|
</td>
|
|
<td>--></td>
|
|
<td align=center>
|
|
C library
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
<p>
|
|
I have still no good conception how one can split C library interfaces
|
|
into type oriented interfaces.
|
|
A Module in Modula-3 represents an Abstract DataType
|
|
(or call it a static classes, i.e. a class without virtual methods).
|
|
E.g. if you have a principal type, say <tt>Database</tt>,
|
|
it is good Modula-3 style to set up one Module with the name <tt>Database</tt>
|
|
where the database type is declared with the name <tt>T</tt>
|
|
and where all functions are declared that operates on it.
|
|
</p>
|
|
|
|
<p>
|
|
The normal operation of SWIG is to generate a fixed set of files per call.
|
|
To generate multiple modules one has to write one SWIG interface
|
|
(different SWIG interfaces can share common data) per module.
|
|
Identifiers belonging to a different module may ignored (<tt>%ignore</tt>)
|
|
and the principal type must be renamed (<tt>%typemap</tt>).
|
|
</p>
|
|
|
|
|
|
<H3><a name="Modula3_cppinterface"></a>27.2.2 Interfaces to C++ libraries</H3>
|
|
|
|
|
|
<p>
|
|
Interfaces to C++ files are much more complicated and
|
|
there are some more design decisions that are not made, yet.
|
|
Modula-3 has no support for C++ functions
|
|
but C++ compilers should support generating C++ functions
|
|
with a C interface.
|
|
</p>
|
|
|
|
<p>
|
|
Here's a scheme of how the function calls to Modula-3 wrappers
|
|
are redirected to C library functions:
|
|
</p>
|
|
|
|
<table summary="Modula-3 C++ library">
|
|
<tr>
|
|
<td align=center>
|
|
Modula-3 wrapper<br>
|
|
Module<tt>.i3</tt><br>
|
|
generated by Modula-3 part of SWIG
|
|
</td>
|
|
<td></td>
|
|
<td align=center>C++ library</td>
|
|
</tr>
|
|
<tr>
|
|
<td align=center>
|
|
<!-- pre tag overrides centering -->
|
|
|<br>
|
|
v
|
|
</td>
|
|
<td></td>
|
|
<td align=center>
|
|
^<br>
|
|
|
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td align=center>
|
|
Modula-3 interface to C<br>
|
|
Module<tt>Raw.i3</tt><br>
|
|
generated by Modula-3 part of SWIG
|
|
</td>
|
|
<td>--></td>
|
|
<td align=center>
|
|
C interface to C++<br>
|
|
module<tt>_wrap.cxx</tt><br>
|
|
generated by the SWIG core
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>
|
|
Wrapping C++ libraries arises additional problems:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
Is it sensible to wrap C++ classes with Modula-3 classes?
|
|
</li>
|
|
<li>
|
|
How to find the wrapping Modula-3 class
|
|
for a class pointer that is returned by a C++ routine?
|
|
</li>
|
|
<li>
|
|
How to deal with multiple inheritance
|
|
which was neglected for Modula-3 for good reasons?
|
|
</li>
|
|
<li>
|
|
Is it possible to sub-class C++ classes with Modula-3 code?
|
|
This issue is addressed by directors,
|
|
a feature that was experimentally added to some Language modules
|
|
like
|
|
<a href="Java.html#Java_directors">Java</a> and
|
|
<a href="Python.html#Python_directors">Python</a>.
|
|
</li>
|
|
<li>
|
|
How to manage storage with the garbage collector of Modula-3?
|
|
Support for
|
|
<a href="Customization.html#Customization_ownership">
|
|
<tt>%newobject</tt> and <tt>%typemap(newfree)</tt></a>
|
|
isn't implemented, yet.
|
|
What's about resources that are managed by the garbage collector
|
|
but shall be passed back to the storage management of the C++ library?
|
|
This is a general issue which is not solved in a satisfying fashion
|
|
as far as I know.
|
|
</li>
|
|
<li>
|
|
How to turn C++ exceptions into Modula-3 exceptions?
|
|
There's also no support for
|
|
<a href="Customization.html#Customization_exception">
|
|
<tt>%exception</tt></a>, yet.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Be warned:
|
|
There is no C++ library I wrote a SWIG interface for,
|
|
so I'm not sure if this is possible or sensible, yet.
|
|
</p>
|
|
|
|
<H2><a name="Modula3_preliminaries"></a>27.3 Preliminaries</H2>
|
|
|
|
|
|
<H3><a name="Modula3_compilers"></a>27.3.1 Compilers</H3>
|
|
|
|
|
|
<p>
|
|
There are different Modula-3 compilers around:
|
|
cm3, pm3, ezm3, Klagenfurth Modula-3, Cambridge Modula-3.
|
|
SWIG itself does not contain compiler specific code
|
|
but the modula3.swg library file
|
|
may do so.
|
|
For testing examples I use Critical Mass cm3.
|
|
</p>
|
|
|
|
|
|
<H3><a name="Modula3_commandline"></a>27.3.2 Additional Commandline Options</H3>
|
|
|
|
|
|
<p>
|
|
There are some experimental command line options
|
|
that prevent SWIG from generating interface files.
|
|
Instead files are emitted that may assist you
|
|
when writing SWIG interface files.
|
|
</p>
|
|
|
|
<table border summary="Modula-3 specific options">
|
|
<tr>
|
|
<th>Modula-3 specific options</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td valign=top>-generateconst <file></td>
|
|
<td>
|
|
Disable generation of interfaces and wrappers.
|
|
Instead write code for computing numeric values of constants
|
|
to the specified file.
|
|
<br>
|
|
C code may contain several constant definitions
|
|
written as preprocessor macros.
|
|
Other language modules of SWIG use
|
|
compute-once-use-readonly variables or
|
|
functions to wrap such definitions.
|
|
All of them can invoke C code dynamically
|
|
for computing the macro values.
|
|
But if one wants to turn them into Modula-3
|
|
integer constants, enumerations or set types,
|
|
the values of these expressions has to be known statically.
|
|
Although definitions like <tt>(1 << FLAG_MAXIMIZEWINDOW)</tt>
|
|
must be considered as good C style
|
|
they are hard to convert to Modula-3
|
|
since the value computation can use every feature of C.
|
|
<br>
|
|
Thus I implemented these switch
|
|
to extract all constant definitions
|
|
and write a C program that output the values of them.
|
|
It works for numeric constants only
|
|
and treats all of them as <tt>double</tt>.
|
|
Future versions may generate a C++ program
|
|
that can detect the type of the macros
|
|
by overloaded output functions.
|
|
Then strings can also be processed.
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td valign=top>-generaterename <file></td>
|
|
<td>
|
|
Disable generation of interfaces and wrappers.
|
|
Instead generate suggestions for <tt>%rename</tt>.
|
|
<br>
|
|
C libraries use a naming style
|
|
that is neither homogeneous nor similar to that of Modula-3.
|
|
C function names often contain a prefix denoting the library
|
|
and some name components separated by underscores
|
|
or capitalization changes.
|
|
To get library interfaces that are really Modula-3 like
|
|
you should rename the function names with the <tt>%rename</tt> directive.
|
|
This switch outputs a list of such directives
|
|
with a name suggestion generated by a simple heuristic.
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td valign=top>-generatetypemap <file></td>
|
|
<td>
|
|
Disable generation of interfaces and wrappers.
|
|
Instead generate templates for some basic typemaps.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<H2><a name="Modula3_typemaps"></a>27.4 Modula-3 typemaps</H2>
|
|
|
|
|
|
<H3><a name="Modula3_inoutparam"></a>27.4.1 Inputs and outputs</H3>
|
|
|
|
|
|
<p>
|
|
Each C procedure has a bunch of inputs and outputs.
|
|
Inputs are passed as function arguments,
|
|
outputs are updated referential arguments and
|
|
the function value.
|
|
</p>
|
|
|
|
<p>
|
|
Each C type can have several typemaps
|
|
that apply only in case if a type is used
|
|
for an input argument, for an output argument,
|
|
or for a return value.
|
|
A further typemap may specify
|
|
the direction that is used for certain parameters.
|
|
I have chosen this separation
|
|
in order to be able to write general typemaps for the modula3.swg typemap library.
|
|
In the library code the final usage of the type is not known.
|
|
Using separate typemaps for each possible use
|
|
allows appropriate definitions for each case.
|
|
If these pre-definitions are fine
|
|
then the direction of the function parameter
|
|
is the only hint the user must give.
|
|
</p>
|
|
|
|
<p>
|
|
The typemaps specific to Modula-3 have a common name scheme:
|
|
A typemap name starts with "m3",
|
|
followed by "raw" or "wrap"
|
|
depending on whether it controls the generation
|
|
of the Module<tt>Raw.i3</tt> or the Module<tt>.i3</tt>, respectively.
|
|
It follows an "in" for typemaps applied to input argument,
|
|
"out" for output arguments, "arg" for all kind of arguments,
|
|
"ret" for returned values.
|
|
</p>
|
|
|
|
<p>
|
|
The main task of SWIG is to build wrapper function,
|
|
i.e. functions that convert values between C and Modula-3
|
|
and call the corresponding C function.
|
|
Modula-3 wrapper functions generated by SWIG
|
|
consist of the following parts:
|
|
</p>
|
|
<ul>
|
|
<li>Generate <tt>PROCEDURE</tt> signature.</li>
|
|
<li>Declare local variables.</li>
|
|
<li>Convert input values from Modula-3 to C.</li>
|
|
<li>Check for input value integrity.</li>
|
|
<li>Call the C function.</li>
|
|
<li>Check returned values, e.g. error codes.</li>
|
|
<li>Convert and write back values into Modula-3 records.</li>
|
|
<li>Free temporary storage.</li>
|
|
<li>Return values.</li>
|
|
</ul>
|
|
|
|
<table border summary="Modula-3 typemaps">
|
|
<tr>
|
|
<th>Typemap</th>
|
|
<th>Example</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapargvar</td>
|
|
<td><tt>$1: INTEGER := $1_name;</tt></td>
|
|
<td>
|
|
Declaration of some variables needed for temporary results.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapargconst</td>
|
|
<td><tt>$1 = "$1_name";</tt></td>
|
|
<td>
|
|
Declaration of some constant, maybe for debug purposes.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapargraw</td>
|
|
<td><tt>ORD($1_name)</tt></td>
|
|
<td>
|
|
The expression that should be passed as argument to the raw Modula-3 interface function.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapargdir</td>
|
|
<td><tt>out</tt></td>
|
|
<td>
|
|
Referential arguments can be used for input, output, update.
|
|
???
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapinmode</td>
|
|
<td><tt>READONLY</tt></td>
|
|
<td>
|
|
One of Modula-3 parameter modes
|
|
<tt>VALUE</tt> (or empty),
|
|
<tt>VAR</tt>,
|
|
<tt>READONLY</tt>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapinname</td>
|
|
<td></td>
|
|
<td>
|
|
New name of the input argument.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapintype</td>
|
|
<td></td>
|
|
<td>
|
|
Modula-3 type of the input argument.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapindefault</td>
|
|
<td></td>
|
|
<td>
|
|
Default value of the input argument
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapinconv</td>
|
|
<td><tt>$1 := M3toC.SharedTtoS($1_name);</tt></td>
|
|
<td>
|
|
Statement for converting the Modula-3 input value to C compliant value.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapincheck</td>
|
|
<td><tt>IF Text.Length($1_name) > 10 THEN RAISE E("str too long"); END;</tt></td>
|
|
<td>
|
|
Check the integrity of the input value.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapoutname</td>
|
|
<td></td>
|
|
<td>
|
|
Name of the <tt>RECORD</tt> field to be used for returning multiple values.
|
|
This applies to referential output arguments that shall be turned
|
|
into return values.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapouttype</td>
|
|
<td></td>
|
|
<td>
|
|
Type of the value that is returned instead of a referential output argument.
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapoutconv</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapoutcheck</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapretraw</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapretname</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wraprettype</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapretvar</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapretconv</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapretcheck</td>
|
|
<td></td>
|
|
<td>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>m3wrapfreearg</td>
|
|
<td><tt>M3toC.FreeSharedS(str,arg1);</tt></td>
|
|
<td>
|
|
Free resources that were temporarily used in the wrapper.
|
|
Since this step should never be skipped,
|
|
SWIG will put it in the <tt>FINALLY</tt> branch
|
|
of a <tt>TRY .. FINALLY</tt> structure.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
|
|
<H3><a name="Modula3_ordinals"></a>27.4.2 Subranges, Enumerations, Sets</H3>
|
|
|
|
|
|
<p>
|
|
Subranges, enumerations, and sets are machine oriented types
|
|
that make Modula very strong and expressive compared
|
|
with the type systems of many other languages.
|
|
</p>
|
|
|
|
<ul>
|
|
<li>
|
|
Subranges are used for statically restricted choices of integers.
|
|
</li>
|
|
<li>
|
|
Enumerations are used for named choices.
|
|
</li>
|
|
<li>
|
|
Sets are commonly used for flag (option) sets.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Using them extensively makes Modula code very safe and readable.
|
|
</p>
|
|
|
|
<p>
|
|
C supports enumerations, too, but they are not as safe as the ones of Modula.
|
|
Thus they are abused for many things:
|
|
For named choices, for integer constant definitions, for sets.
|
|
To make it complete every way of defining a value in C
|
|
(<tt>#define</tt>, <tt>const int</tt>, <tt>enum</tt>)
|
|
is somewhere used for defining something
|
|
that must be handled completely different in Modula-3
|
|
(<tt>INTEGER</tt>, enumeration, <tt>SET</tt>).
|
|
</p>
|
|
|
|
<p>
|
|
I played around with several <tt>%feature</tt>s and <tt>%pragma</tt>s
|
|
that split the task up into converting
|
|
the C bit patterns (integer or bit set)
|
|
into Modula-3 bit patterns (integer or bit set)
|
|
and change the type as requested.
|
|
See the corresponding example in the
|
|
Examples/modula3/enum/example.i file.
|
|
This is quite messy and not satisfying.
|
|
So the best what you can currently do is
|
|
to rewrite constant definitions manually.
|
|
Though this is a tedious work
|
|
that I'd like to automate.
|
|
</p>
|
|
|
|
|
|
<H3><a name="Modula3_class"></a>27.4.3 Objects</H3>
|
|
|
|
|
|
<p>
|
|
Declarations of C++ classes are mapped to <tt>OBJECT</tt> types
|
|
while it is tried to retain the access hierarchy
|
|
"public - protected - private" using partial revelation.
|
|
Though the example in
|
|
Examples/modula3/class/example.i
|
|
is not really useful, yet.
|
|
</p>
|
|
|
|
|
|
<H3><a name="Modula3_imports"></a>27.4.4 Imports</H3>
|
|
|
|
|
|
<p>
|
|
Pieces of Modula-3 code provided by typemaps
|
|
may contain identifiers from foreign modules.
|
|
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
|
|
contains code using the function <tt>M3toC.SharedTtoS</tt>
|
|
you may declare <tt>%typemap("m3wrapinconv:import") blah * %{M3toC%}</tt>.
|
|
Then the module <tt>M3toC</tt> is imported
|
|
if the <tt>m3wrapinconv</tt> typemap for <tt>blah *</tt>
|
|
is used at least once.
|
|
Use <tt>%typemap("m3wrapinconv:import") blah * %{MyConversions AS M3toC%}</tt>
|
|
if you need module renaming.
|
|
Unqualified import is not supported.
|
|
</p>
|
|
|
|
<p>
|
|
It is cumbersome to add this typemap to each piece of Modula-3 code.
|
|
It is especially useful when writing general typemaps
|
|
for the modula3.swg typemap library.
|
|
For a monolithic module you might be better off
|
|
if you add the imports directly:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%insert(m3rawintf) %{
|
|
IMPORT M3toC;
|
|
%}
|
|
</pre></div>
|
|
|
|
|
|
<H3><a name="Modula3_exceptions"></a>27.4.5 Exceptions</H3>
|
|
|
|
|
|
<p>
|
|
Modula-3 provides another possibility
|
|
of an output of a function: exceptions.
|
|
</p>
|
|
|
|
<p>
|
|
Any piece of Modula-3 code that SWIG inserts
|
|
due to a typemap can raise an exception.
|
|
This way you can also convert an error code
|
|
from a C function into a Modula-3 exception.
|
|
</p>
|
|
|
|
<p>
|
|
The <tt>RAISES</tt> clause is controlled
|
|
by typemaps with the <tt>throws</tt> extension.
|
|
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
|
|
contains code that may raise the exceptions <tt>OSError.E</tt>
|
|
you should declare
|
|
<tt>%typemap("m3wrapinconv:throws") blah * %{OSError.E%}</tt>.
|
|
</p>
|
|
|
|
<H3><a name="Modula3_typemap_example"></a>27.4.6 Example</H3>
|
|
|
|
|
|
<p>
|
|
The generation of wrappers in Modula-3 needs very fine control
|
|
to take advantage of the language features.
|
|
Here is an example of a generated wrapper
|
|
where almost everything is generated by a typemap:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
<I> (* %relabel m3wrapinmode m3wrapinname m3wrapintype m3wrapindefault *)</I>
|
|
PROCEDURE Name (READONLY str : TEXT := "" )
|
|
<I> (* m3wrapoutcheck:throws *)</I>
|
|
: NameResult RAISES {E} =
|
|
CONST
|
|
arg1name = "str"; <I>(* m3wrapargconst *)</I>
|
|
VAR
|
|
arg0 : C.char_star; <I>(* m3wrapretvar *)</I>
|
|
arg1 : C.char_star; <I>(* m3wrapargvar *)</I>
|
|
arg2 : C.int;
|
|
result : RECORD
|
|
<I> (*m3wrapretname m3wraprettype*)</I>
|
|
unixPath : TEXT;
|
|
<I> (*m3wrapoutname m3wrapouttype*)</I>
|
|
checksum : CARDINAL;
|
|
END;
|
|
BEGIN
|
|
TRY
|
|
arg1 := M3toC.SharedTtoS(str); <I>(* m3wrapinconv *)</I>
|
|
IF Text.Length(arg1) > 10 THEN <I>(* m3wrapincheck *)</I>
|
|
RAISE E("str too long");
|
|
END;
|
|
<I> (* m3wrapretraw m3wrapargraw *)</I>
|
|
arg0 := MessyToUnix (arg1, arg2);
|
|
result.unixPath := M3toC.CopyStoT(arg0); <I>(* m3wrapretconv *)</I>
|
|
result.checksum := arg2; <I>(* m3wrapoutconv *)</I>
|
|
IF result.checksum = 0 THEN <I>(* m3wrapoutcheck *)</I>
|
|
RAISE E("invalid checksum");
|
|
END;
|
|
FINALLY
|
|
M3toC.FreeSharedS(str,arg1); <I>(* m3wrapfreearg *)</I>
|
|
END;
|
|
END Name;
|
|
</pre></div>
|
|
|
|
|
|
<H2><a name="Modula3_hints"></a>27.5 More hints to the generator</H2>
|
|
|
|
|
|
<H3><a name="Modula3_features"></a>27.5.1 Features</H3>
|
|
|
|
|
|
<table border summary="Modula-3 features">
|
|
<tr>
|
|
<th>Feature</th>
|
|
<th>Example</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>multiretval</td>
|
|
<td><tt>%m3multiretval get_box;</tt> or
|
|
<tt>%feature("modula3:multiretval") get_box;</tt></td>
|
|
<td>Let the denoted function return a <tt>RECORD</tt>
|
|
rather than a plain value.
|
|
This <tt>RECORD</tt> contains all arguments with "out" direction
|
|
including the return value of the C function (if there is one).
|
|
If more than one argument is "out"
|
|
then the function <b>must</b> have the <tt>multiretval</tt> feature activated,
|
|
but it is explicitly requested from the user to prevent mistakes.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>constnumeric</td>
|
|
<td><tt>%constnumeric(12) twelve;</tt> or
|
|
<tt>%feature("constnumeric","12") twelve;</tt></td>
|
|
<td>This feature can be used to tell Modula-3's back-end of SWIG
|
|
the value of an identifier.
|
|
This is necessary in the cases
|
|
where it was defined by a non-trivial C expression.
|
|
This feature is used by the
|
|
<tt>-generateconst</tt> <a href="#Modula3_commandline">option</a>.
|
|
In future it may be generalized to other kind of values
|
|
such as strings.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<H3><a name="Modula3_pragmas"></a>27.5.2 Pragmas</H3>
|
|
|
|
|
|
<table border summary="Modula-3 pragmas">
|
|
<tr>
|
|
<th>Pragma</th>
|
|
<th>Example</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>unsafe</td>
|
|
<td><tt>%pragma(modula3) unsafe="true";</tt></td>
|
|
<td>Mark the raw interface modules as <tt>UNSAFE</tt>.
|
|
This will be necessary in many cases.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>library</td>
|
|
<td><tt>%pragma(modula3) library="m3fftw";</tt></td>
|
|
<td>Specifies the library name for the wrapper library to be created.
|
|
It should be distinct from the name of the library to be wrapped.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<H2><a name="Modula3_remarks"></a>27.6 Remarks</H2>
|
|
|
|
|
|
<ul>
|
|
<li>
|
|
The Modula-3 part of SWIG doesn't try to generate nicely formatted code.
|
|
If you need to read the generated code, use <tt>m3pp</tt> to postprocess the
|
|
Modula files.
|
|
</li>
|
|
</ul>
|
|
|
|
</body>
|
|
</html>
|