This section describes how Modula-2 implementation modules can be called from Python (and other scripting languages such as TCL and Perl). GNU Modula-2 can be instructed to create a swig interface when it is compiling an implementation module. Swig then uses the interface file to generate all the necessary wrapping to that the desired scripting language may access the implementation module.
Here is an example of how you might call upon the services of the
Modula-2 library module NumberIO
from Python3.
The following commands can be used to generate the Python3 module:
export src=‘directory to the sources’ export prefix=‘directory to where the compiler is installed’ gm2 -I${src} -c -g -fswig ${src}/../../../gm2-libs/NumberIO.mod gm2 -I${src} -c -g -fmakelist ${src}/../../../gm2-libs/NumberIO.mod gm2 -I${src} -c -g -fmakeinit -fshared \ ${src}/../../../gm2-libs/NumberIO.mod swig -c++ -python3 NumberIO.i libtool --mode=compile g++ -g -c -I${src} NumberIO_m2.cpp \ -o NumberIO_m2.lo libtool --tag=CC --mode=compile gm2 -g -c \ -I${src}../../../gm2-libs \ ${src}/../../../gm2-libs/NumberIO.mod -o NumberIO.lo libtool --tag=CC --mode=compile g++ -g -c NumberIO_wrap.cxx \ -I/usr/include/python3 -o NumberIO_wrap.lo libtool --mode=link gcc -g NumberIO_m2.lo NumberIO_wrap.lo \ -L${prefix}/lib64 \ -rpath `pwd` -lgm2 -lstdc++ -lm -o libNumberIO.la cp .libs/libNumberIO.so _NumberIO.so
The first four commands, generate the swig interface file NumberIO.i and python wrap files NumberIO_wrap.cxx and NumberIO.py. The next three libtool commnads compile the C++ and Modula-2 source code into .lo objects. The last libtool command links all the .lo files into a .la file and includes all shared library dependencies.
Now it is possible to run the following Python script (called testnum.py):
import NumberIO print ("1234 x 2 =", NumberIO.NumberIO_StrToInt("1234")*2)
like this:
$ python3 testnum.py 1234 x 2 = 2468
See (gm2)Producing a Python module for another example which
uses the UNQUALIFIED
keyword to reduce the module name clutter
from the viewport of Python3.
This section discusses the limitations of automatically generating
swig files. From the previous example we see that the module
NumberIO
had a swig interface file NumberIO.i
automatically generated by the compiler. If we consider three of the
procedure definitions in NumberIO.def we can see the
success and limitations of the automatic interface generation.
PROCEDURE StrToHex (a: ARRAY OF CHAR; VAR x: CARDINAL) ; PROCEDURE StrToInt (a: ARRAY OF CHAR; VAR x: INTEGER) ; PROCEDURE ReadInt (VAR x: CARDINAL) ;
Below are the swig interface prototypes:
extern void NumberIO_StrToHex (char *_m2_address_a, int _m2_high_a, unsigned int *OUTPUT); /* parameters: x is known to be an OUTPUT */ extern void NumberIO_StrToInt (char *_m2_address_a, int _m2_high_a, int *OUTPUT); /* parameters: x is guessed to be an OUTPUT */ extern void NumberIO_ReadInt (int *x); /* parameters: x is unknown */
In the case of StrToHex
it can be seen that the compiler
detects that the last parameter is an output. It explicitly tells
swig this by using the parameter name OUTPUT
and in the
following comment it informs the user that it knows this to be an
output parameter. In the second procedure StrToInt
it marks
the final parameter as an output, but it tells the user that this is
only a guess. Finally in ReadInt
it informs the user that
it does not know whether the parameter, x
, is an output, input
or an inout parameter.
The compiler decides whether to mark a parameter as either:
INPUT
, OUTPUT
or INOUT
if it is read before
written or visa versa in the first basic block. At this point
it will write output that the parameter is known. If it is not
read or written in the first basic block then subsequent basic blocks
are searched and the result is commented as a guess. Finally if
no read or write occurs then the parameter is commented as unknown.
However, clearly it is possible to fool this mechanism. Nevertheless
automatic generation of implementation module into swig interface files
was thought sufficiently useful despite these limitations.
In conclusion it would be wise to check all parameters in any
automatically generated swig interface file. Furthermore you can
force the automatic mechanism to generate correct interface files by
reading or writing to the VAR
parameter in the first basic
block of a procedure.