| <!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">29 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">29.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">29.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">29.2 Conception</a></H2> |
| |
| |
| <H3><a name="Modula3_cinterface">29.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">29.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">29.3 Preliminaries</a></H2> |
| |
| |
| <H3><a name="Modula3_compilers">29.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">29.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">29.4 Modula-3 typemaps</a></H2> |
| |
| |
| <H3><a name="Modula3_inoutparam">29.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">29.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">29.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">29.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">29.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">29.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">29.5 More hints to the generator</a></H2> |
| |
| |
| <H3><a name="Modula3_features">29.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">29.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">29.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> |