[Modula3] Remove code for Modula3
We dropped support for it in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2 years. See #2009.
This commit is contained in:
parent
f3ba54c3bb
commit
12f3a85916
29 changed files with 6 additions and 6521 deletions
|
|
@ -1,942 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>SWIG and Modula-3</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
<body bgcolor="#FFFFFF">
|
||||
<H1><a name="Modula3">31 SWIG and Modula-3</a></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">31.1 Overview</a></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">31.1.1 Motivation</a></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">31.2 Conception</a></H2>
|
||||
|
||||
|
||||
<H3><a name="Modula3_cinterface">31.2.1 Interfaces to C libraries</a></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">31.2.2 Interfaces to C++ libraries</a></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">31.3 Preliminaries</a></H2>
|
||||
|
||||
|
||||
<H3><a name="Modula3_compilers">31.3.1 Compilers</a></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">31.3.2 Additional Commandline Options</a></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">31.4 Modula-3 typemaps</a></H2>
|
||||
|
||||
|
||||
<H3><a name="Modula3_inoutparam">31.4.1 Inputs and outputs</a></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">31.4.2 Subranges, Enumerations, Sets</a></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">31.4.3 Objects</a></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">31.4.4 Imports</a></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">31.4.5 Exceptions</a></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">31.4.6 Example</a></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">31.5 More hints to the generator</a></H2>
|
||||
|
||||
|
||||
<H3><a name="Modula3_features">31.5.1 Features</a></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">31.5.2 Pragmas</a></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">31.6 Remarks</a></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>
|
||||
Loading…
Add table
Add a link
Reference in a new issue