previous next top contents index framed top this page unframed
The compiler subcommands required to specify the FLIs to and from C are
FLI TC and FLI FC.
The default output file name for the MAINSAIL FLI compilers is:
9.1. FLI Compilers
The Foreign Call Compiler (FCC) is used to call foreign procedures from
MAINSAIL. The MAINSAIL Entry Compiler (MEC) is used to call MAINSAIL
PROCEDUREs from a foreign language.
If the foreign language to be called
does not conform to the C calling conventions, then the standard FLI
compilers cannot be used. Contact XIDAK
if you need an interface between
such a language and NTPNT MAINSAIL.
module name, converted to lower case.s
9.2. Data Types
Use the appropriate
C data type macros ($CSHORT, $CINT, etc.;
see Appendix L of the MAINSAIL Language Manual)
when declaring parameter types for FLI procedures
(on NTPNT, this works even for MAINSAIL versions before
16.29).
In addition, use the correspondences below for data types not listed in Appendix L of the MAINSAIL Language Manual:
| C Type | MAINSAIL Type | Representation Passed |
|---|---|---|
| pointer | POINTER, ADDRESS | 4 bytes |
| char array or char * | STRING, CHARADR, $REFERENCE $CHAR $INPLACEARRAY | address of first character (STRING passed to C must be explicitly NUL-terminated) |
| array | ARRAY, $REFERENCE $INPLACEARRAY | address of first element |
| dataType * | ADDRESS, $REFERENCE to aligned CLASS | address of record or first ARRAY element |
USES parameters are passed by value. MODIFIES, PRODUCES, and $REFERENCE parameters are passed by reference. The C * operator may be used when declaring MODIFIES, PRODUCES, and $REFERENCE parameters.
USES parameters of MAINSAIL types STRING and POINTER can be passed from MAINSAIL to C. Parameters of MAINSAIL types POINTER and STRING cannot be passed from C to MAINSAIL. MODIFIES and PRODUCES parameters of MAINSAIL types STRING and POINTER are not allowed.
MAINSAIL STRINGs can be directly passed to C, i.e., the parameter is declared using the MAINSAIL STRING data type. C expects strings to be terminated with a NUL byte; $cStr(s) can be used to append a NUL byte to the MAINSAIL STRING s.
When a MAINSAIL POINTER is passed to C, the C structure and the MAINSAIL CLASS must be declared such that the data in the structure are accessed correctly by both languages; use the $ALIGN directive to accomplish this.
Inplace ARRAYs and records can be passed only as $REFERENCE parameters.
The MAINSAIL representation of a BOOLEAN should be translated into C as a short, with 0 representing MAINSAIL FALSE and 1 representing MAINSAIL TRUE.
A MAINSAIL NULLARRAY is passed
to C as a Zero address. C must check that
the address is non-Zero before
accessing any array elements if there is
a possibility that a MAINSAIL NULLARRAY has been passed.
In order to get the address of the first element of a MAINSAIL
ARRAY that is not a parameter, but rather
a field or element of a data structure passed to
C, you must use the C function xiAdrOfFirstElement;
see Section 7.9 of the MAINSAIL Compiler User's Guide.
9.2.1. MAINSAIL and C Arrays
ARRAY parameters are passed to C
by passing the address of the first
element of the ARRAY.
The Foreign Call Compiler generates code to
convert each MAINSAIL dynamic ARRAY parameter to the
address of its first element.
MAINSAIL stores ARRAYs in row-major form. If your C
implementation does not follow this
convention, care must be taken with
the indices.
9.3. Caveat
When dealing with collectable MAINSAIL data types (STRINGs,
POINTERs,
and dynamic ARRAYs),
care must be taken not to violate the data boundaries.
Overwriting the wrong parts of these structures may cause MAINSAIL to
crash in ways that are difficult to trace. If, for example, a garbage
collection link is destroyed, MAINSAIL may run until a collection is
triggered, at which point the results are unpredictable.
9.4. MAINSAIL Foreign Call Compiler Example
Suppose that the MAINSAIL MODULE CALLC
calls the C procedure proc1.
Figures 9–1, 9–2, and 9–3
show the MODULE CALLC, the C procedure
proc1, and the MAINSAIL FLI MODULE MSTOC, respectively.
Figure 9–1. MAINSAIL MODULE CALLC That Calls C Procedure proc1
| MODULE CALLC (in file callc.msl):
BEGIN "callC" |
| C procedure proc1 (in file cproc.c):
proc1 (i,j,k,c,p,s,ary) |
Figure 9–3. MAINSAIL Foreign Language Interface MODULE MSTOC
| MAINSAIL MODULE MSTOC (in file mstoc.msl):
BEGIN "msToC" |
Take the following steps to compile and link the program of Figures 9–1, 9–2, and 9–3:
*compil<eol>
MAINSAIL (R) compiler
Copyright (c) ...
compile (? for help): callc.msl<eol>
Opening intmod for $SYS...
callc.msl 1 ...
Objmod for CALLC on callc-mpn.obj
Intmod for CALLC not stored
compile (? for help): mstoc.msl,<eol>
>fli tc<eol>
><eol>
Opening intmod for $SYS...
mstoc.msl 1 ...
Output for MSTOC on mstoc.s
Intmod for MSTOC not stored
compile (? for help):
*
*conf<eol>
MAINSAIL (R) Bootstrap Configurator
Restoring configuration values from file
c:\mainsail\16.20.1\ntpnt.cnf
CONF: bootfilename fcc.s<eol>
CONF: foreignmodules<eol>
FOREIGNMODULES is
...
Should be:
=<eol>
MSTOC<eol>
<eol>
CONF: <eol>
Bootstrap written in file fcc.s
*<eol>
C:\MYDIR>cl /c cproc.c<eol>
C:\MYDIR>ml /c /coff fcc.s<eol>
C:\MYDIR>ml /c /coff mstoc.s<eol>
C:\MYDIR>link -out:fcc.exe fcc.obj cproc.obj mstoc.obj @c:\mainsail\16.20.1\m.txt<eol>
C:\MYDIR>fcc<eol>
MAINSAIL (R) Version 16.20.1 (? for help)
...
*callc<eol>
Suppose that the C procedure callms is to call the MAINSAIL PROCEDURE proc1. Figures 9–4, 9–5, 9–6, and 9–7 show the C procedure callms, the MAINSAIL MODULE MSMOD that contains the PROCEDURE proc1, the MAINSAIL FLI MODULE MSTOC, and the MAINSAIL MODULE CALLC that calls the C procedure callms, respectively.
Figure 9–4. C Procedure That Calls MAINSAIL PROCEDURE proc1
| C program (in file callms.c):
callms () |
Figure 9–5. MAINSAIL MODULE MSMOD Called by C Procedure callms
| MAINSAIL MODULE MSMOD (in file msmod.msl):
BEGIN "msMod" |
Figure 9–6. MAINSAIL Foreign Language Interface MODULE MSTOC
| MAINSAIL MODULE MSTOC (in file mstoc.msl):
BEGIN "msToC" |
Figure 9–7. MAINSAIL MODULE CALLC That Calls C Procedure callms
| MAINSAIL MODULE CALLC (in file callc.msl):
BEGIN "callC" |
Follow these steps to compile and run callms:
*compil<eol>
MAINSAIL (R) Compiler
Copyright...
compile (? for help): msmod.msl<eol>
Opening intmod for $SYS...
msmod.msl 1 ...
compile (? for help): callc.msl<eol>
Opening intmod for $SYS...
callc.msl ...
compile (? for help): msmod.msl,<eol>
>fli fc<eol>
><eol>
Opening intmod for $SYS...
msmod.msl 1 ...
compile (? for help): mstoc.msl,<eol>
>fli tc<eol>
><eol>
Opening intmod for $SYS...
mstoc.msl ...
compile (? for help): <eol>
*<eol>
*conf<eol>
MAINSAIL (R) Bootstrap Configurator
Restoring configuration values from file
c:\mainsail\16.20.1\ntpnt.cnf
CONF: bootfilename mec.s<eol>
CONF: foreignmodules<eol>
FOREIGNMODULES is
...
Should be:
=<eol>
MSTOC<eol>
<eol>
CONF: <eol>
Bootstrap written in file mec.s
*<eol>
C:\MYDIR>cl /c callms.c<eol>
C:\MYDIR>ml /c /coff mec.s<eol>
C:\MYDIR>ml /c /coff msmod.s<eol>
C:\MYDIR>ml /c /coff mstoc.s<eol>
C:\MYDIR>link -out:mec.exe mec.obj msmod.obj mstoc.obj callms.obj @c:\mainsail\16.20.1\m.txt<eol>
C:\MYDIR>mec<eol>
MAINSAIL (R) Version 16.20.1 (? for help)
...
*callc<eol>
Result is 3
If the foreign program is to start execution (i.e., the function main is part of your C program), you must modify the above sequence of steps as follows:
CONF: configurationbits =!'H8<eol>
This sets the $foreignCodeStartsExecution bit in the bootstrap so that MAINSAIL's initialization will not conflict with C's.
MAINSAIL System-Specific User's Guides, Chapter 9