Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 | <html> | |
3 | <head> | |
4 | <title>SWIG and Modula-3</title> | |
5 | <link rel="stylesheet" type="text/css" href="style.css"> | |
6 | </head> | |
7 | <body bgcolor="#FFFFFF"> | |
8 | <H1><a name="Modula3"></a>20 SWIG and Modula-3</H1> | |
9 | <!-- INDEX --> | |
10 | <div class="sectiontoc"> | |
11 | <ul> | |
12 | <li><a href="#modula3_overview">Overview</a> | |
13 | <ul> | |
14 | <li><a href="#whyscripting">Why not scripting ?</a> | |
15 | <li><a href="#whymodula3">Why Modula-3 ?</a> | |
16 | <li><a href="#whycpp">Why C / C++ ?</a> | |
17 | <li><a href="#whyswig">Why SWIG ?</a> | |
18 | </ul> | |
19 | <li><a href="#conception">Conception</a> | |
20 | <ul> | |
21 | <li><a href="#cinterface">Interfaces to C libraries</a> | |
22 | <li><a href="#cppinterface">Interfaces to C++ libraries</a> | |
23 | </ul> | |
24 | <li><a href="#preliminaries">Preliminaries</a> | |
25 | <ul> | |
26 | <li><a href="#compilers">Compilers</a> | |
27 | <li><a href="#commandline">Additional Commandline Options</a> | |
28 | </ul> | |
29 | <li><a href="#modula3_typemaps">Modula-3 typemaps</a> | |
30 | <ul> | |
31 | <li><a href="#inoutparam">Inputs and outputs</a> | |
32 | <li><a href="#ordinals">Subranges, Enumerations, Sets</a> | |
33 | <li><a href="#class">Objects</a> | |
34 | <li><a href="#imports">Imports</a> | |
35 | <li><a href="#exceptions">Exceptions</a> | |
36 | <li><a href="#typemap_example">Example</a> | |
37 | </ul> | |
38 | <li><a href="#hints">More hints to the generator</a> | |
39 | <ul> | |
40 | <li><a href="#features">Features</a> | |
41 | <li><a href="#pragmas">Pragmas</a> | |
42 | </ul> | |
43 | <li><a href="#remarks">Remarks</a> | |
44 | </ul> | |
45 | </div> | |
46 | <!-- INDEX --> | |
47 | ||
48 | ||
49 | ||
50 | <p> | |
51 | This chapter describes SWIG's support of | |
52 | <a href="http://www.m3.org/">Modula-3</a>. | |
53 | You should be familiar with the | |
54 | <a href="SWIG.html#SWIG">basics</a> | |
55 | of SWIG, | |
56 | especially | |
57 | <a href="Typemaps.html">typemaps</a>. | |
58 | </p> | |
59 | ||
60 | <H2><a name="modula3_overview"></a>20.1 Overview</H2> | |
61 | ||
62 | ||
63 | <p> | |
64 | The Modula-3 support is very basic and highly experimental! | |
65 | Many features are still not designed satisfyingly | |
66 | and I need more discussion about the odds and ends. | |
67 | Don't rely on any feature, incompatible changes are likely in the future! | |
68 | The Modula-3 generator was already useful for interfacing | |
69 | to the libraries | |
70 | </p> | |
71 | ||
72 | <ol> | |
73 | <li> | |
74 | <a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/plplot/"> | |
75 | PLPlot | |
76 | </a> | |
77 | </li> | |
78 | <li> | |
79 | <a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/fftw/"> | |
80 | FFTW | |
81 | </a> . | |
82 | </li> | |
83 | </ol> | |
84 | ||
85 | ||
86 | <p> | |
87 | I took some more time to explain | |
88 | why I think it's right what I'm doing. | |
89 | So the introduction got a bit longer than it should ... ;-) | |
90 | </p> | |
91 | ||
92 | ||
93 | <H3><a name="whyscripting"></a>20.1.1 Why not scripting ?</H3> | |
94 | ||
95 | ||
96 | <p> | |
97 | SWIG started as wrapper from the fast compiled languages C and C++ | |
98 | to high level scripting languages like Python. | |
99 | Although scripting languages are designed | |
100 | to make programming life easier | |
101 | by hiding machine internals from the programmer | |
102 | there are several aspects of todays scripting languages | |
103 | that are unfavourable in my opinion. | |
104 | </p> | |
105 | ||
106 | <p> | |
107 | Besides C, C++, Cluster (a Modula derivate for Amiga computers) | |
108 | I evaluated several scripting like languages in the past: | |
109 | Different dialects of BASIC, | |
110 | Perl, ARexx (a variant of Rexx for Amiga computers), | |
111 | shell scripts. | |
112 | I found them too inconsistent, | |
113 | too weak in distinguishing types, | |
114 | too weak in encapsulating pieces of code. | |
115 | Eventually I have started several projects in Python | |
116 | because of the fine syntax. | |
117 | But when projects became larger | |
118 | I lost the track. | |
119 | I got convinced that one can not have | |
120 | maintainable code in a language | |
121 | that is not statically typed. | |
122 | In fact the main advantages of scripting languages | |
123 | e.g. matching regular expressions, | |
124 | complex built-in datatypes like lists, dictionaries, | |
125 | are not advantages of the language itself | |
126 | but can be provided by function libraries. | |
127 | </p> | |
128 | ||
129 | <H3><a name="whymodula3"></a>20.1.2 Why Modula-3 ?</H3> | |
130 | ||
131 | ||
132 | <p> | |
133 | Modula-3 is a compiler language | |
134 | in the tradition of Niklaus Wirth's Modula 2, | |
135 | which is in turn a successor of the popular Pascal. | |
136 | I have chosen Modula-3 | |
137 | because of its | |
138 | logical syntax, | |
139 | strong modularization, | |
140 | the type system which is very detailed | |
141 | for machine types compared to other languages. | |
142 | Of course it supports all of the modern games | |
143 | like exceptions, objects, garbage collection, threads. | |
144 | While C++ programmers must | |
145 | control three languages, | |
146 | namely the preprocessor, C and ++, | |
147 | Modula-3 is made in one go | |
148 | and the language definition is really compact. | |
149 | </p> | |
150 | ||
151 | <p> | |
152 | On the one hand Modula-3 can be safe | |
153 | (but probably less efficient) in normal modules | |
154 | while providing much static and dynamic safety. | |
155 | On the other hand you can write efficient | |
156 | but less safe code in the style of C | |
157 | within <tt>UNSAFE</tt> modules. | |
158 | </p> | |
159 | ||
160 | <p> | |
161 | Unfortunately Modula's safety and strength | |
162 | requires more writing than scripting languages do. | |
163 | Today if I want to safe characters | |
164 | I prefer Haskell (similar to OCAML) - | |
165 | it's statically typed, too. | |
166 | </p> | |
167 | ||
168 | ||
169 | <H3><a name="whycpp"></a>20.1.3 Why C / C++ ?</H3> | |
170 | ||
171 | ||
172 | <p> | |
173 | Although it is no problem to write Modula-3 programs | |
174 | that performs as fast as C | |
175 | most libraries are not written in Modula-3 but in C. | |
176 | Fortunately the binary interface of most function libraries | |
177 | can be addressed by Modula-3. | |
178 | Even more fortunately even non-C libraries may provide C header files. | |
179 | This is where SWIG becomes helpful. | |
180 | </p> | |
181 | ||
182 | <H3><a name="whyswig"></a>20.1.4 Why SWIG ?</H3> | |
183 | ||
184 | ||
185 | <p> | |
186 | The C headers and the possibility to interface to C libraries | |
187 | still leaves the work for you | |
188 | to write Modula-3 interfaces to them. | |
189 | To make things comfortable you will also need | |
190 | wrappers that convert between high-level features of Modula-3 | |
191 | (garbage collecting, exceptions) | |
192 | and the low level of the C libraries. | |
193 | </p> | |
194 | ||
195 | <p> | |
196 | SWIG converts C headers to Modula-3 interfaces for you. | |
197 | You could call the C functions without loss | |
198 | of efficiency but it won't be joy | |
199 | because you could not pass <tt>TEXT</tt>s | |
200 | or open arrays and | |
201 | you would have to process error return codes | |
202 | rather then exceptions. | |
203 | But using some typemaps SWIG will also generate | |
204 | wrappers that bring the whole Modula-3 comfort to you. | |
205 | If the library API is ill designed | |
206 | writing appropriate typemaps can be still time-consuming. | |
207 | E.g. C programmers are very creative to work-around | |
208 | missing data types like (real) enumerations and sets. | |
209 | You should turn such work-arounds back to the Modula-3 way | |
210 | otherwise you lose static safety and consistency. | |
211 | </p> | |
212 | ||
213 | <p> | |
214 | ||
215 | But you have still a problem: | |
216 | C library interfaces are often ill. | |
217 | They lack for certain information | |
218 | because C compilers wouldn't care about. | |
219 | You should integrate detailed type information | |
220 | by adding <tt>typedef</tt>s and <tt>const</tt>s | |
221 | and you should persuade the C library programmer | |
222 | to add this information to his interface. | |
223 | Only this way other language users can benefit from your work | |
224 | and only this way you can easily update your interfaces | |
225 | when a new library version is released. | |
226 | ||
227 | You will realise that writing <b>good</b> SWIG interfaces | |
228 | is very costly and it will only amortise | |
229 | when considering evolving libraries. | |
230 | </p> | |
231 | ||
232 | ||
233 | <p> | |
234 | Without SWIG you would probably never consider | |
235 | to call C++ libraries from Modula-3. | |
236 | But with SWIG this is worth a consideration. | |
237 | SWIG can write C wrappers to C++ functions and object methods | |
238 | that may throw exceptions. | |
239 | In fact it breaks down C++ libraries to C interfaces | |
240 | which can be in turn called from Modula-3. | |
241 | To make it complete you can hide the C interface | |
242 | with Modula-3 classes and exceptions. | |
243 | </p> | |
244 | ||
245 | <p> | |
246 | Although SWIG does the best it can do | |
247 | it can only serve as a one-way strategy. | |
248 | That means you can use C++ libraries | |
249 | with Modula-3 (even with call back functions), | |
250 | but it's certainly not possible to smoothly | |
251 | integrate Modula-3 code into a C / C++ project. | |
252 | </p> | |
253 | ||
254 | ||
255 | <H2><a name="conception"></a>20.2 Conception</H2> | |
256 | ||
257 | ||
258 | <H3><a name="cinterface"></a>20.2.1 Interfaces to C libraries</H3> | |
259 | ||
260 | ||
261 | <p> | |
262 | Modula-3 has an integrated support for calling C functions. | |
263 | This is also extensively used by the standard Modula-3 libraries | |
264 | to call OS functions. | |
265 | The Modula-3 part of SWIG and the corresponding SWIG library | |
266 | <a href="../../Lib/modula3/modula3.swg"><tt>modula3.swg</tt></a> | |
267 | contain code that uses these features. | |
268 | Because of the built-in support there is no need | |
269 | for calling the SWIG kernel to generate wrappers written in C. | |
270 | All conversion and argument checking can be done in Modula-3 | |
271 | and the interfacing is quite efficient. | |
272 | All you have to do is to write pieces of Modula-3 code | |
273 | that SWIG puts together. | |
274 | </p> | |
275 | ||
276 | <table border summary="Modula-3 C library support"> | |
277 | <tr><th colspan=2>C library support integrated in Modula-3<th></tr> | |
278 | <tr> | |
279 | <td>Pragma <tt><* EXTERNAL *></tt></td> | |
280 | <td>Precedes a declaration of a PROCEDURE that is implemented | |
281 | in an external library instead of a Modula-3 module.</td> | |
282 | </tr> | |
283 | <tr> | |
284 | <td>Pragma <tt><* CALLBACK *></tt></td> | |
285 | <td>Precedes a declaration of a PROCEDURE that should be called | |
286 | by external library code.</td> | |
287 | </tr> | |
288 | <tr> | |
289 | <td>Module <tt>Ctypes</tt></td> | |
290 | <td>Contains Modula-3 types that match some basic C types.</td> | |
291 | </tr> | |
292 | <tr> | |
293 | <td>Module <tt>M3toC</tt></td> | |
294 | <td>Contains routines that convert between Modula-3's <tt>TEXT</tt> type | |
295 | and C's <tt>char *</tt> type.</td> | |
296 | </tr> | |
297 | </table> | |
298 | ||
299 | <p> | |
300 | In each run of SWIG the Modula-3 part | |
301 | generates several files: | |
302 | </p> | |
303 | <table border summary="Modula-3 generated files"> | |
304 | <tr> | |
305 | <th>Module name scheme</th> | |
306 | <th>Identifier for <tt>%insert</tt></th> | |
307 | <th>Description</th> | |
308 | </tr> | |
309 | <tr> | |
310 | <td>Module<tt>Raw.i3</tt></td> | |
311 | <td><tt>m3rawintf</tt></td> | |
312 | <td>Declaration of types that are equivalent to those of the C library, | |
313 | <tt>EXTERNAL</tt> procedures as interface to the C library functions</td> | |
314 | </tr> | |
315 | <tr> | |
316 | <td>Module<tt>Raw.m3</tt></td> | |
317 | <td><tt>m3rawimpl</tt></td> | |
318 | <td>Almost empty.</td> | |
319 | </tr> | |
320 | <tr> | |
321 | <td>Module<tt>.i3</tt></td> | |
322 | <td><tt>m3wrapintf</tt></td> | |
323 | <td>Declaration of comfortable wrappers to the C library functions.</td> | |
324 | </tr> | |
325 | <tr> | |
326 | <td>Module<tt>.m3</tt></td> | |
327 | <td><tt>m3wrapimpl</tt></td> | |
328 | <td>Implementation of the wrappers that | |
329 | convert between Modula-3 and C types, | |
330 | check for validity of values, | |
331 | hand-over resource management to the garbage collector using <tt>WeakRef</tt>s | |
332 | and raises exceptions.</td> | |
333 | </tr> | |
334 | <tr> | |
335 | <td><tt>m3makefile</tt></td> | |
336 | <td><tt>m3makefile</tt></td> | |
337 | <td>Add the modules above to the Modula-3 project and | |
338 | specify the name of the Modula-3 wrapper library | |
339 | to be generated. | |
340 | ||
341 | Today I'm not sure if it is a good idea | |
342 | to create a <tt>m3makefile</tt> in each run, | |
343 | because SWIG must be started for each Modula-3 module it creates. | |
344 | Thus the m3makefile is overwritten each time. :-( | |
345 | </td> | |
346 | </tr> | |
347 | </table> | |
348 | ||
349 | <p> | |
350 | Here's a scheme of how the function calls to Modula-3 wrappers | |
351 | are redirected to C library functions: | |
352 | </p> | |
353 | ||
354 | <table summary="Modula-3 C library"> | |
355 | <tr> | |
356 | <td align=center> | |
357 | Modula-3 wrapper<br> | |
358 | Module<tt>.i3</tt><br> | |
359 | generated by Modula-3 part of SWIG | |
360 | </td> | |
361 | <td></td> | |
362 | <td align=center></td> | |
363 | </tr> | |
364 | <tr> | |
365 | <td align=center> | |
366 | <!-- pre tag overrides centering --> | |
367 | |<br> | |
368 | v | |
369 | </td> | |
370 | <td></td> | |
371 | <td align=center></td> | |
372 | </tr> | |
373 | <tr> | |
374 | <td align=center> | |
375 | Modula-3 interface to C<br> | |
376 | Module<tt>Raw.i3</tt><br> | |
377 | generated by Modula-3 part of SWIG | |
378 | </td> | |
379 | <td>--></td> | |
380 | <td align=center> | |
381 | C library | |
382 | </td> | |
383 | </tr> | |
384 | </table> | |
385 | ||
386 | ||
387 | <p> | |
388 | I have still no good conception how one can split C library interfaces | |
389 | into type oriented interfaces. | |
390 | A Module in Modula-3 represents an Abstract DataType | |
391 | (or call it a static classes, i.e. a class without virtual methods). | |
392 | E.g. if you have a principal type, say <tt>Database</tt>, | |
393 | it is good Modula-3 style to set up one Module with the name <tt>Database</tt> | |
394 | where the database type is declared with the name <tt>T</tt> | |
395 | and where all functions are declared that operates on it. | |
396 | </p> | |
397 | ||
398 | <p> | |
399 | The normal operation of SWIG is to generate a fixed set of files per call. | |
400 | To generate multiple modules one has to write one SWIG interface | |
401 | (different SWIG interfaces can share common data) per module. | |
402 | Identifiers belonging to a different module may ignored (<tt>%ignore</tt>) | |
403 | and the principal type must be renamed (<tt>%typemap</tt>). | |
404 | </p> | |
405 | ||
406 | ||
407 | <H3><a name="cppinterface"></a>20.2.2 Interfaces to C++ libraries</H3> | |
408 | ||
409 | ||
410 | <p> | |
411 | Interfaces to C++ files are much more complicated and | |
412 | there are some more design decisions that are not made, yet. | |
413 | Modula-3 has no support for C++ functions | |
414 | but C++ compilers should support generating C++ functions | |
415 | with a C interface. | |
416 | </p> | |
417 | ||
418 | <p> | |
419 | Here's a scheme of how the function calls to Modula-3 wrappers | |
420 | a redirected to C library functions: | |
421 | </p> | |
422 | ||
423 | <table summary="Modula-3 C++ library"> | |
424 | <tr> | |
425 | <td align=center> | |
426 | Modula-3 wrapper<br> | |
427 | Module<tt>.i3</tt><br> | |
428 | generated by Modula-3 part of SWIG | |
429 | </td> | |
430 | <td></td> | |
431 | <td align=center>C++ library</td> | |
432 | </tr> | |
433 | <tr> | |
434 | <td align=center> | |
435 | <!-- pre tag overrides centering --> | |
436 | |<br> | |
437 | v | |
438 | </td> | |
439 | <td></td> | |
440 | <td align=center> | |
441 | ^<br> | |
442 | | | |
443 | </td> | |
444 | </tr> | |
445 | <tr> | |
446 | <td align=center> | |
447 | Modula-3 interface to C<br> | |
448 | Module<tt>Raw.i3</tt><br> | |
449 | generated by Modula-3 part of SWIG | |
450 | </td> | |
451 | <td>--></td> | |
452 | <td align=center> | |
453 | C interface to C++<br> | |
454 | module<tt>_wrap.cxx</tt><br> | |
455 | generated by the SWIG core | |
456 | </td> | |
457 | </tr> | |
458 | </table> | |
459 | ||
460 | <p> | |
461 | Wrapping C++ libraries arises additional problems: | |
462 | </p> | |
463 | <ul> | |
464 | <li> | |
465 | Is it sensible to wrap C++ classes with Modula-3 classes? | |
466 | </li> | |
467 | <li> | |
468 | How to find the wrapping Modula-3 class | |
469 | for a class pointer that is returned by a C++ routine? | |
470 | </li> | |
471 | <li> | |
472 | How to deal with multiple inheritance | |
473 | which was neglected for Modula-3 for good reasons? | |
474 | </li> | |
475 | <li> | |
476 | Is it possible to sub-class C++ classes with Modula-3 code? | |
477 | This issue is addressed by directors, | |
478 | a feature that was experimentally added to some Language modules | |
479 | like | |
480 | <a href="Java.html#java_directors">Java</a> and | |
481 | <a href="Python.html#directors">Python</a>. | |
482 | </li> | |
483 | <li> | |
484 | How to manage storage with the garbage collector of Modula-3? | |
485 | Support for | |
486 | <a href="Customization.html#ownership"> | |
487 | <tt>%newobject</tt> and <tt>%typemap(newfree)</tt></a> | |
488 | isn't implemented, yet. | |
489 | What's about resources that are managed by the garbage collector | |
490 | but shall be passed back to the storage management of the C++ library? | |
491 | This is a general issue which is not solved in a satisfying fashion | |
492 | as far as I know. | |
493 | </li> | |
494 | <li> | |
495 | How to turn C++ exceptions into Modula-3 exceptions? | |
496 | There's also no support for | |
497 | <a href="Customization.html#exception"> | |
498 | <tt>%exception</tt></a>, yet. | |
499 | </li> | |
500 | </ul> | |
501 | ||
502 | <p> | |
503 | Be warned: | |
504 | There is no C++ library I wrote a SWIG interface for, | |
505 | so I'm not sure if this is possible or sensible, yet. | |
506 | </p> | |
507 | ||
508 | <H2><a name="preliminaries"></a>20.3 Preliminaries</H2> | |
509 | ||
510 | ||
511 | <H3><a name="compilers"></a>20.3.1 Compilers</H3> | |
512 | ||
513 | ||
514 | <p> | |
515 | There are different Modula-3 compilers around: | |
516 | cm3, pm3, ezm3, Klagenfurth Modula-3, Cambridge Modula-3. | |
517 | SWIG itself does not contain compiler specific code | |
518 | but the library file | |
519 | <a href="../../Lib/modula3/modula3.swg"><tt>modula3.swg</tt></a> | |
520 | may do so. | |
521 | For testing examples I use Critical Mass cm3. | |
522 | </p> | |
523 | ||
524 | ||
525 | <H3><a name="commandline"></a>20.3.2 Additional Commandline Options</H3> | |
526 | ||
527 | ||
528 | <p> | |
529 | There are some experimental command line options | |
530 | that prevent SWIG from generating interface files. | |
531 | Instead files are emitted that may assist you | |
532 | when writing SWIG interface files. | |
533 | </p> | |
534 | ||
535 | <table border summary="Modula-3 specific options"> | |
536 | <tr> | |
537 | <th>Modula-3 specific options</th> | |
538 | <th>Description</th> | |
539 | </tr> | |
540 | ||
541 | <tr> | |
542 | <td valign=top>-generateconst <file></td> | |
543 | <td> | |
544 | Disable generation of interfaces and wrappers. | |
545 | Instead write code for computing numeric values of constants | |
546 | to the specified file. | |
547 | <br> | |
548 | C code may contain several constant definitions | |
549 | written as preprocessor macros. | |
550 | Other language modules of SWIG use | |
551 | compute-once-use-readonly variables or | |
552 | functions to wrap such definitions. | |
553 | All of them can invoke C code dynamically | |
554 | for computing the macro values. | |
555 | But if one wants to turn them into Modula-3 | |
556 | integer constants, enumerations or set types, | |
557 | the values of these expressions has to be known statically. | |
558 | Although definitions like <tt>(1 << FLAG_MAXIMIZEWINDOW)</tt> | |
559 | must be considered as good C style | |
560 | they are hard to convert to Modula-3 | |
561 | since the value computation can use every feature of C. | |
562 | <br> | |
563 | Thus I implemented these switch | |
564 | to extract all constant definitions | |
565 | and write a C program that output the values of them. | |
566 | It works for numeric constants only | |
567 | and treats all of them as <tt>double</tt>. | |
568 | Future versions may generate a C++ program | |
569 | that can detect the type of the macros | |
570 | by overloaded output functions. | |
571 | Then strings can also be processed. | |
572 | </td> | |
573 | </tr> | |
574 | ||
575 | <tr> | |
576 | <td valign=top>-generaterename <file></td> | |
577 | <td> | |
578 | Disable generation of interfaces and wrappers. | |
579 | Instead generate suggestions for <tt>%rename</tt>. | |
580 | <br> | |
581 | C libraries use a naming style | |
582 | that is neither homogenous nor similar to that of Modula-3. | |
583 | C function names often contain a prefix denoting the library | |
584 | and some name components separated by underscores | |
585 | or capitalization changes. | |
586 | To get library interfaces that are really Modula-3 like | |
587 | you should rename the function names with the <tt>%rename</tt> directive. | |
588 | This switch outputs a list of such directives | |
589 | with a name suggestion generated by a simple heuristic. | |
590 | </td> | |
591 | </tr> | |
592 | ||
593 | <tr> | |
594 | <td valign=top>-generatetypemap <file></td> | |
595 | <td> | |
596 | Disable generation of interfaces and wrappers. | |
597 | Instead generate templates for some basic typemaps. | |
598 | </td> | |
599 | </tr> | |
600 | </table> | |
601 | ||
602 | <H2><a name="modula3_typemaps"></a>20.4 Modula-3 typemaps</H2> | |
603 | ||
604 | ||
605 | <H3><a name="inoutparam"></a>20.4.1 Inputs and outputs</H3> | |
606 | ||
607 | ||
608 | <p> | |
609 | Each C procedure has a bunch of inputs and outputs. | |
610 | Inputs are passed as function arguments, | |
611 | outputs are updated referential arguments and | |
612 | the function value. | |
613 | </p> | |
614 | ||
615 | <p> | |
616 | Each C type can have several typemaps | |
617 | that apply only in case if a type is used | |
618 | for an input argument, for an output argument, | |
619 | or for a return value. | |
620 | A further typemap may specify | |
621 | the direction that is used for certain parameters. | |
622 | I have chosen this separation | |
623 | in order to be able to write general typemaps for the typemap library | |
624 | <a href="../../Lib/modula3/modula3.swg"><tt>modula3.swg</tt></a> | |
625 | . | |
626 | In the library code the final usage of the type is not known. | |
627 | Using separate typemaps for each possible use | |
628 | allows appropriate definitions for each case. | |
629 | If these pre-definitions are fine | |
630 | then the direction of the function parameter | |
631 | is the only hint the user must give. | |
632 | </p> | |
633 | ||
634 | <p> | |
635 | The typemaps specific to Modula-3 have a common name scheme: | |
636 | A typemap name starts with "m3", | |
637 | followed by "raw" or "wrap" | |
638 | depending on whether it controls the generation | |
639 | of the Module<tt>Raw.i3</tt> or the Module<tt>.i3</tt>, respectively. | |
640 | It follows an "in" for typemaps applied to input argument, | |
641 | "out" for output arguments, "arg" for all kind of arguments, | |
642 | "ret" for returned values. | |
643 | </p> | |
644 | ||
645 | <p> | |
646 | The main task of SWIG is to build wrapper function, | |
647 | i.e. functions that convert values between C and Modula-3 | |
648 | and call the corresponding C function. | |
649 | Modula-3 wrapper functions generated by SWIG | |
650 | consist of the following parts: | |
651 | </p> | |
652 | <ul> | |
653 | <li>Generate <tt>PROCEDURE</tt> signature.</li> | |
654 | <li>Declare local variables.</li> | |
655 | <li>Convert input values from Modula-3 to C.</li> | |
656 | <li>Check for input value integrity.</li> | |
657 | <li>Call the C function.</li> | |
658 | <li>Check returned values, e.g. error codes.</li> | |
659 | <li>Convert and write back values into Modula-3 records.</li> | |
660 | <li>Free temporary storage.</li> | |
661 | <li>Return values.</li> | |
662 | </ul> | |
663 | ||
664 | <table border summary="Modula-3 typemaps"> | |
665 | <tr> | |
666 | <th>Typemap</th> | |
667 | <th>Example</th> | |
668 | <th>Description</th> | |
669 | </tr> | |
670 | <tr> | |
671 | <td>m3wrapargvar</td> | |
672 | <td><tt>$1: INTEGER := $1_name;</tt></td> | |
673 | <td> | |
674 | Declaration of some variables needed for temporary results. | |
675 | </td> | |
676 | </tr> | |
677 | <tr> | |
678 | <td>m3wrapargconst</td> | |
679 | <td><tt>$1 = "$1_name";</tt></td> | |
680 | <td> | |
681 | Declaration of some constant, maybe for debug purposes. | |
682 | </td> | |
683 | </tr> | |
684 | <tr> | |
685 | <td>m3wrapargraw</td> | |
686 | <td><tt>ORD($1_name)</tt></td> | |
687 | <td> | |
688 | The expression that should be passed as argument to the raw Modula-3 interface function. | |
689 | </td> | |
690 | </tr> | |
691 | <tr> | |
692 | <td>m3wrapargdir</td> | |
693 | <td><tt>out</tt></td> | |
694 | <td> | |
695 | Referential arguments can be used for input, output, update. | |
696 | ??? | |
697 | </td> | |
698 | </tr> | |
699 | <tr> | |
700 | <td>m3wrapinmode</td> | |
701 | <td><tt>READONLY</tt></td> | |
702 | <td> | |
703 | One of Modula-3 parameter modes | |
704 | <tt>VALUE</tt> (or empty), | |
705 | <tt>VAR</tt>, | |
706 | <tt>READONLY</tt> | |
707 | </td> | |
708 | </tr> | |
709 | <tr> | |
710 | <td>m3wrapinname</td> | |
711 | <td></td> | |
712 | <td> | |
713 | New name of the input argument. | |
714 | </td> | |
715 | </tr> | |
716 | <tr> | |
717 | <td>m3wrapintype</td> | |
718 | <td></td> | |
719 | <td> | |
720 | Modula-3 type of the input argument. | |
721 | </td> | |
722 | </tr> | |
723 | <tr> | |
724 | <td>m3wrapindefault</td> | |
725 | <td></td> | |
726 | <td> | |
727 | Default value of the input argument | |
728 | </td> | |
729 | </tr> | |
730 | <tr> | |
731 | <td>m3wrapinconv</td> | |
732 | <td><tt>$1 := M3toC.SharedTtoS($1_name);</tt></td> | |
733 | <td> | |
734 | Statement for converting the Modula-3 input value to C compliant value. | |
735 | </td> | |
736 | </tr> | |
737 | <tr> | |
738 | <td>m3wrapincheck</td> | |
739 | <td><tt>IF Text.Length($1_name) > 10 THEN RAISE E("str too long"); END;</tt></td> | |
740 | <td> | |
741 | Check the integrity of the input value. | |
742 | </td> | |
743 | </tr> | |
744 | <tr> | |
745 | <td>m3wrapoutname</td> | |
746 | <td></td> | |
747 | <td> | |
748 | Name of the <tt>RECORD</tt> field to be used for returning multiple values. | |
749 | This applies to referential output arguments that shall be turned | |
750 | into return values. | |
751 | </td> | |
752 | </tr> | |
753 | <tr> | |
754 | <td>m3wrapouttype</td> | |
755 | <td></td> | |
756 | <td> | |
757 | Type of the value that is returned instead of a referential output argument. | |
758 | </td> | |
759 | </tr> | |
760 | <tr> | |
761 | <td>m3wrapoutconv</td> | |
762 | <td></td> | |
763 | <td> | |
764 | </td> | |
765 | </tr> | |
766 | <tr> | |
767 | <td>m3wrapoutcheck</td> | |
768 | <td></td> | |
769 | <td> | |
770 | </td> | |
771 | </tr> | |
772 | <tr> | |
773 | <td>m3wrapretraw</td> | |
774 | <td></td> | |
775 | <td> | |
776 | </td> | |
777 | </tr> | |
778 | <tr> | |
779 | <td>m3wrapretname</td> | |
780 | <td></td> | |
781 | <td> | |
782 | </td> | |
783 | </tr> | |
784 | <tr> | |
785 | <td>m3wraprettype</td> | |
786 | <td></td> | |
787 | <td> | |
788 | </td> | |
789 | </tr> | |
790 | <tr> | |
791 | <td>m3wrapretvar</td> | |
792 | <td></td> | |
793 | <td> | |
794 | </td> | |
795 | </tr> | |
796 | <tr> | |
797 | <td>m3wrapretconv</td> | |
798 | <td></td> | |
799 | <td> | |
800 | </td> | |
801 | </tr> | |
802 | <tr> | |
803 | <td>m3wrapretcheck</td> | |
804 | <td></td> | |
805 | <td> | |
806 | </td> | |
807 | </tr> | |
808 | <tr> | |
809 | <td>m3wrapfreearg</td> | |
810 | <td><tt>M3toC.FreeSharedS(str,arg1);</tt></td> | |
811 | <td> | |
812 | Free resources that were temporarily used in the wrapper. | |
813 | Since this step should never be skipped, | |
814 | SWIG will put it in the <tt>FINALLY</tt> branch | |
815 | of a <tt>TRY .. FINALLY</tt> structure. | |
816 | </td> | |
817 | </tr> | |
818 | </table> | |
819 | ||
820 | ||
821 | <H3><a name="ordinals"></a>20.4.2 Subranges, Enumerations, Sets</H3> | |
822 | ||
823 | ||
824 | <p> | |
825 | Subranges, enumerations, and sets are machine oriented types | |
826 | that make Modula very strong and expressive compared | |
827 | with the type systems of many other languages. | |
828 | </p> | |
829 | ||
830 | <ul> | |
831 | <li> | |
832 | Subranges are used for statically restricted choices of integers. | |
833 | </li> | |
834 | <li> | |
835 | Enumerations are used for named choices. | |
836 | </li> | |
837 | <li> | |
838 | Sets are commonly used for flag (option) sets. | |
839 | </li> | |
840 | </ul> | |
841 | ||
842 | <p> | |
843 | Using them extensively makes Modula code very safe and readable. | |
844 | </p> | |
845 | ||
846 | <p> | |
847 | C supports enumerations, too, but they are not as safe as the ones of Modula. | |
848 | Thus they are abused for many things: | |
849 | For named choices, for integer constant definitions, for sets. | |
850 | To make it complete every way of defining a value in C | |
851 | (<tt>#define</tt>, <tt>const int</tt>, <tt>enum</tt>) | |
852 | is somewhere used for defining something | |
853 | that must be handled completely different in Modula-3 | |
854 | (<tt>INTEGER</tt>, enumeration, <tt>SET</tt>). | |
855 | </p> | |
856 | ||
857 | <p> | |
858 | I played around with several <tt>%feature</tt>s and <tt>%pragma</tt>s | |
859 | that split the task up into converting | |
860 | the C bit patterns (integer or bit set) | |
861 | into Modula-3 bit patterns (integer or bit set) | |
862 | and change the type as requested. | |
863 | See the corresponding | |
864 | <a href="../../Examples/modula3/enum/example.i">example</a>. | |
865 | This is quite messy and not satisfying. | |
866 | So the best what you can currently do is | |
867 | to rewrite constant definitions manually. | |
868 | Though this is a tedious work | |
869 | that I'd like to automate. | |
870 | </p> | |
871 | ||
872 | ||
873 | <H3><a name="class"></a>20.4.3 Objects</H3> | |
874 | ||
875 | ||
876 | <p> | |
877 | Declarations of C++ classes are mapped to <tt>OBJECT</tt> types | |
878 | while it is tried to retain the access hierarchy | |
879 | "public - protected - private" using partial revelation. | |
880 | Though the | |
881 | <a href="../../Examples/modula3/class/example.i">implementation</a> | |
882 | is not really useful, yet. | |
883 | </p> | |
884 | ||
885 | ||
886 | <H3><a name="imports"></a>20.4.4 Imports</H3> | |
887 | ||
888 | ||
889 | <p> | |
890 | Pieces of Modula-3 code provided by typemaps | |
891 | may contain identifiers from foreign modules. | |
892 | If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt> | |
893 | contains code using the function <tt>M3toC.SharedTtoS</tt> | |
894 | you may declare <tt>%typemap("m3wrapinconv:import") blah * %{M3toC%}</tt>. | |
895 | Then the module <tt>M3toC</tt> is imported | |
896 | if the <tt>m3wrapinconv</tt> typemap for <tt>blah *</tt> | |
897 | is used at least once. | |
898 | Use <tt>%typemap("m3wrapinconv:import") blah * %{MyConversions AS M3toC%}</tt> | |
899 | if you need module renaming. | |
900 | Unqualified import is not supported. | |
901 | </p> | |
902 | ||
903 | <p> | |
904 | It is cumbersome to add this typemap to each piece of Modula-3 code. | |
905 | It is especially useful when writing general typemaps | |
906 | for the typemap library | |
907 | <a href="../../Lib/modula3/modula3.swg"><tt>modula3.swg</tt></a> | |
908 | . | |
909 | For a monolithic module you might be better off | |
910 | if you add the imports directly: | |
911 | </p> | |
912 | ||
913 | <div class="code"> | |
914 | <pre> | |
915 | %insert(m3rawintf) %{ | |
916 | IMPORT M3toC; | |
917 | %} | |
918 | </pre></div> | |
919 | ||
920 | ||
921 | <H3><a name="exceptions"></a>20.4.5 Exceptions</H3> | |
922 | ||
923 | ||
924 | <p> | |
925 | Modula-3 provides another possibility | |
926 | of an output of a function: exceptions. | |
927 | </p> | |
928 | ||
929 | <p> | |
930 | Any piece of Modula-3 code that SWIG inserts | |
931 | due to a typemap can raise an exception. | |
932 | This way you can also convert an error code | |
933 | from a C function into a Modula-3 exception. | |
934 | </p> | |
935 | ||
936 | <p> | |
937 | The <tt>RAISES</tt> clause is controlled | |
938 | by typemaps with the <tt>throws</tt> extension. | |
939 | If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt> | |
940 | contains code that may raise the exceptions <tt>OSError.E</tt> | |
941 | you should declare | |
942 | <tt>%typemap("m3wrapinconv:throws") blah * %{OSError.E%}</tt>. | |
943 | </p> | |
944 | ||
945 | <H3><a name="typemap_example"></a>20.4.6 Example</H3> | |
946 | ||
947 | ||
948 | <p> | |
949 | The generation of wrappers in Modula-3 needs very fine control | |
950 | to take advantage of the language features. | |
951 | Here is an example of a generated wrapper | |
952 | where almost everything is generated by a typemap: | |
953 | </p> | |
954 | ||
955 | <div class="code"><pre> | |
956 | <I> (* %relabel m3wrapinmode m3wrapinname m3wrapintype m3wrapindefault *)</I> | |
957 | PROCEDURE Name (READONLY str : TEXT := "" ) | |
958 | <I> (* m3wrapoutcheck:throws *)</I> | |
959 | : NameResult RAISES {E} = | |
960 | CONST | |
961 | arg1name = "str"; <I>(* m3wrapargconst *)</I> | |
962 | VAR | |
963 | arg0 : C.char_star; <I>(* m3wrapretvar *)</I> | |
964 | arg1 : C.char_star; <I>(* m3wrapargvar *)</I> | |
965 | arg2 : C.int; | |
966 | result : RECORD | |
967 | <I> (*m3wrapretname m3wraprettype*)</I> | |
968 | unixPath : TEXT; | |
969 | <I> (*m3wrapoutname m3wrapouttype*)</I> | |
970 | checksum : CARDINAL; | |
971 | END; | |
972 | BEGIN | |
973 | TRY | |
974 | arg1 := M3toC.SharedTtoS(str); <I>(* m3wrapinconv *)</I> | |
975 | IF Text.Length(arg1) > 10 THEN <I>(* m3wrapincheck *)</I> | |
976 | RAISE E("str too long"); | |
977 | END; | |
978 | <I> (* m3wrapretraw m3wrapargraw *)</I> | |
979 | arg0 := MessyToUnix (arg1, arg2); | |
980 | result.unixPath := M3toC.CopyStoT(arg0); <I>(* m3wrapretconv *)</I> | |
981 | result.checksum := arg2; <I>(* m3wrapoutconv *)</I> | |
982 | IF result.checksum = 0 THEN <I>(* m3wrapoutcheck *)</I> | |
983 | RAISE E("invalid checksum"); | |
984 | END; | |
985 | FINALLY | |
986 | M3toC.FreeSharedS(str,arg1); <I>(* m3wrapfreearg *)</I> | |
987 | END; | |
988 | END Name; | |
989 | </pre></div> | |
990 | ||
991 | ||
992 | <H2><a name="hints"></a>20.5 More hints to the generator</H2> | |
993 | ||
994 | ||
995 | <H3><a name="features"></a>20.5.1 Features</H3> | |
996 | ||
997 | ||
998 | <table border summary="Modula-3 features"> | |
999 | <tr> | |
1000 | <th>Feature</th> | |
1001 | <th>Example</th> | |
1002 | <th>Description</th> | |
1003 | </tr> | |
1004 | <tr> | |
1005 | <td>multiretval</td> | |
1006 | <td><tt>%m3multiretval get_box;</tt> or | |
1007 | <tt>%feature("modula3:multiretval") get_box;</tt></td> | |
1008 | <td>Let the denoted function return a <tt>RECORD</tt> | |
1009 | rather than a plain value. | |
1010 | This <tt>RECORD</tt> contains all arguments with "out" direction | |
1011 | including the return value of the C function (if there is one). | |
1012 | If more than one argument is "out" | |
1013 | then the function <b>must</b> have the <tt>multiretval</tt> feature activated, | |
1014 | but it is explicitly requested from the user to prevent mistakes.</td> | |
1015 | </tr> | |
1016 | <tr> | |
1017 | <td>constnumeric</td> | |
1018 | <td><tt>%constnumeric(12) twelve;</tt> or | |
1019 | <tt>%feature("constnumeric","12") twelve;</tt></td> | |
1020 | <td>This feature can be used to tell Modula-3's back-end of SWIG | |
1021 | the value of an identifier. | |
1022 | This is necessary in the cases | |
1023 | where it was defined by a non-trivial C expression. | |
1024 | This feature is used by the | |
1025 | <tt>-generateconst</tt> <a href="#options">option</a>. | |
1026 | In future it may be generalized to other kind of values | |
1027 | such as strings. | |
1028 | </td> | |
1029 | </tr> | |
1030 | </table> | |
1031 | ||
1032 | <H3><a name="pragmas"></a>20.5.2 Pragmas</H3> | |
1033 | ||
1034 | ||
1035 | <table border summary="Modula-3 pragmas"> | |
1036 | <tr> | |
1037 | <th>Pragma</th> | |
1038 | <th>Example</th> | |
1039 | <th>Description</th> | |
1040 | </tr> | |
1041 | <tr> | |
1042 | <td>unsafe</td> | |
1043 | <td><tt>%pragma(modula3) unsafe="true";</tt></td> | |
1044 | <td>Mark the raw interface modules as <tt>UNSAFE</tt>. | |
1045 | This will be necessary in many cases.</td> | |
1046 | </tr> | |
1047 | <tr> | |
1048 | <td>library</td> | |
1049 | <td><tt>%pragma(modula3) library="m3fftw";</tt></td> | |
1050 | <td>Specifies the library name for the wrapper library to be created. | |
1051 | It should be distinct from the name of the library to be wrapped.</td> | |
1052 | </tr> | |
1053 | </table> | |
1054 | ||
1055 | <H2><a name="remarks"></a>20.6 Remarks</H2> | |
1056 | ||
1057 | ||
1058 | <ul> | |
1059 | <li> | |
1060 | The Modula-3 part of SWIG doesn't try to generate nicely formatted code. | |
1061 | Use <tt>m3pp</tt> to postprocess the Modula files, | |
1062 | it does a very good job here. | |
1063 | </li> | |
1064 | </ul> | |
1065 | ||
1066 | </body> | |
1067 | </html> |