MAINSAIL System-Specific User's Guides, Chapter 10

previous   next   top   contents   index   framed top   this page unframed


10. Foreign Language Interface

This section contains UNIX-specific information for the MAINSAIL Foreign Language Interface (FLI). Refer to Chapter 7 of the MAINSAIL Compiler User's Guide for a general description of the FLI.

10.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. Under UNIX, the FCC interfaces to C and is available on all available flavors of UNIX. The MEC also interfaces to C and is available for the flavors listed in Appendix A. 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 wish an interface between such a language and UNIX MAINSAIL.

The compiler subcommands required to specify the FLIs to and from C are FLI TC and FLI FC, except as documented in Appendix A.

The default output file name for the MAINSAIL FLI compilers is:

module name, converted to lower case.s

10.2. Data Types

It is strongly recommended (starting with Version 16.29 of MAINSAIL) that you 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 (this is not recommended in earlier versions of MAINSAIL because the FLI compiler did not take explicit sizes of parameter data types into account).

For older code that does not use the C data type macros, and for data types not listed in Appendix L of the MAINSAIL Language Manual, Table 10–1 shows how C data types are mapped to MAINSAIL data types on UNIX operating systems. The byte sizes shown are usual for C implementations on byte-addressable machines, although it is possible that users may encounter a dialect of C with data types of sizes other than those shown in Table 10–1; if so, the following discussion must be modified accordingly.

Table 10–1. MAINSAIL and C Parameter Data Types
C Type MAINSAIL Type Representation Passed
short BOOLEAN, INTEGER, BITS 2 bytes
long LONG INTEGER, LONG BITS same size as POINTER or ADDRESS
pointer POINTER, ADDRESS 4 bytes on 32-bit platform; 8 bytes on 64-bit platform
float REAL 4 bytes
double LONG REAL 8 bytes
char array STRING, CHARADR address of first character (STRING passed to C must be explicitly NUL-terminated)
array (passed from MAINSAIL to C) ARRAY address of first element
dataType * (passed from C to MAINSAIL) ADDRESS address of first element

USES parameters are passed by value. MODIFIES and PRODUCES parameters are passed by reference. The C * operator may be used when declaring MODIFIES and PRODUCES 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; cWrite(s,0) or s := $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. Some flavors of UNIX have data alignment requirements that affect the location of members in C structures; see Appendix A for more information.

The MAINSAIL representation of a BOOLEAN should be translated into C as a short, with 0 representing MAINSAIL FALSE and 1 representing MAINSAIL TRUE.

10.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 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.

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.

An ARRAY field of a MAINSAIL class is represented as a POINTER to the ARRAY data, but a C array member of a struct is included inline in the struct. Consequently, a POINTER to a MAINSAIL CLASS containing ARRAY fields cannot be mapped to a C struct containing array members. For example, consider the MAINSAIL CLASS and C struct declarations:

MAINSAIL C
CLASS c (
    
INTEGER field1;
    
REAL ARRAY(1 TO 3) field2;
    
LONG INTEGER field3,field4;
    
INTEGER ARRAY(1 TO 4) field5;
    
REAL field6;
);
struct c {
    
short field1;
    
float field2[3];
    
long field3,field4;
    
short field5[4];
    
float field6;
}

In memory, records of these types might look like Figure 10–2.

Figure 10–2. MAINSAIL and C Arrays in a CLASS/struct
<diagram>

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.

10.3. Caveat: Beware of Overwriting Data

When dealing with collectable MAINSAIL data types (STRINGs, POINTERs, and 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.

To prevent data that would normally be collectable from being moved by the MAINSAIL memory manager, it may be useful to put those data in an anchored area, as described in Section 25.4 of the MAINSAIL Language Manual.

Appendix A lists other restrictions and caveats for specific UNIX flavors.

10.4. ANSI C FLI Caveat

Currently, each UNIX FLI code generator follows the K & R C argument passing conventions, which are:

Such conversions are typically not performed for arguments and results of functions declared with ANSI function prototypes. Thus, ANSI function prototypes should not be used to declare the C functions that correspond to FLI PROCEDUREs if the C functions have either short or float arguments passed by value or short or float results.

This restriction does not imply that only K & R C compilers may be used to compile C functions that correspond to FLI PROCEDUREs; ANSI C compilers may be used as well. It implies only that C functions must be declared using the K & R C syntax.

For example, corresponding to the following MAINSAIL PROCEDURE header:

$CFLOAT PROCEDURE p ($CSHORT i$CLFOAT r);

you should declare the C function p as:

float p (ir)
short i;
float r;

instead of:

float p (short ifloat r)

10.5. MAINSAIL Foreign Call Compiler Example

Suppose that the MAINSAIL MODULE CALLC calls the C procedure proc1. Figures
10–3, 10–4, and 10–5 show the MODULE CALLC, the C procedure proc1, and the MAINSAIL FLI MODULE MSTOC, respectively. Example 10–6 shows how to compile and run CALLC.

Figure 10–3. MAINSAIL MODULE CALLC That Calls C Procedure proc1
MODULE CALLC (in file callc.msl):

BEGIN "callC"

MODULE msToC (
    
PROCEDURE proc1 (
        
PRODUCES $CSHORT        i;
        
$CSHORT                 j,k;
        
PRODUCES CHARADR        c;
        
POINTER(cl)             p;
        
STRING                  s;
        
BOOLEAN($shortSizeARRAY(1 TO 2)
                                
ary);
or, before Version 16.29, declare proc1 this way:
    
PROCEDURE proc1 (
        
PRODUCES INTEGER        i;
        
INTEGER                 j,k;
        
PRODUCES CHARADR        c;
        
POINTER(cl)             p;
        
STRING                  s;
        
BOOLEAN($shortSizeARRAY(1 TO 2)
                                
ary);
    );

CLASS cl ($CINT li1,li2);

INITIAL PROCEDURE;
BEGIN
INTEGER                 i;
STRING                  s;
POINTER(cl)             p;
CHARADR                 c,cc;
BOOLEAN ARRAY(1 TO 2)   ary;
C procedure proc1 does the following:
#   (1) 
adds j and k and returns the result in i
#   (2) 
creates a string and returns the address of its
#       
first character in c
#   (3) 
swaps the values of the fields of CLASS c1
#   (4) 
prints the value of s
#   (5) 
sets ary[1] to be FALSE
p := new(cl); p.li1 := 1L; p.li2 := 2L;
s := "Hello there!" & cvcs(0);
new(ary); ary[1] := ary[2] := TRUE;
proc1(i,1,2,c,p,s,ary);
write(logFile,"i = ",i,eol);
i := 0; cc := cWHILE cRead(ccDO i .+ 1;
write(logFile,
    "
String returned by proc1 = ",newString(c,i),eol &
    "
p.li1 = ",p.li1,"; p.li2 = ",p.li2,eol &
    "
ary[1] = ary[2]: ",
        
IF ary[1] = ary[2] THEN "TRUEEL "FALSE",eol);
END;

END "callC"

Figure 10–4. C Procedure proc1
C procedure proc1 (in file cproc.c):

proc1 (i,j,k,c,p,s,ary)
short *i;
short j,k;
char **c;
struct {int li1,li2;} *p;
char s[];
short ary[];
{
int temp;
*
i = j + k;
*
c = "Bye for now..."; /* New value for string */
temp = p->li1p->li1 = p->li2p->li2 = temp;
printf("String is %s\n",s);
ary[1] = 0;
}

Figure 10–5. MAINSAIL Foreign Language Interface MODULE MSTOC
MAINSAIL MODULE MSTOC (in file mstoc.msl):

BEGIN "msToC"

MODULE msToC (
    
PROCEDURE proc1 (
        
PRODUCES $CSHORT        i;
        
$CSHORT                 j,k;
        
PRODUCES CHARADR        c;
        
POINTER(cl)             p;
        
STRING                  s;
        
BOOLEAN($shortSizeARRAY(1 TO 2)
                                
ary);
or, before Version 16.29, declare proc1 this way:
    
PROCEDURE proc1 (
        
PRODUCES INTEGER        i;
        
INTEGER                 j,k;
        
PRODUCES CHARADR        c;
        
POINTER(cl)             p;
        
STRING                  s;
        
BOOLEAN($shortSizeARRAY(1 TO 2)
                                
ary);
    );

PROCEDURE proc1 (
    
PRODUCES $CSHORT        i;
    
$CSHORT                 j,k;
    
PRODUCES CHARADR        c;
    
POINTER(cl)             p;
    
STRING                  s;
    
BOOLEAN($shortSizeARRAY(1 TO 2)
                            
ary);;
or, before Version 16.29, declare proc1 this way:
PROCEDURE proc1 (
    
PRODUCES INTEGER        i;
    
INTEGER                 j,k;
    
PRODUCES CHARADR        c;
    
POINTER(cl)             p;
    
STRING                  s;
    
BOOLEAN($shortSizeARRAY(1 TO 2)
                            
ary);;

END "msToC"

Example 10–6. MAINSAIL to C Example
  1. Compile CALLC with the MAINSAIL UNIX compiler. Compile MSTOC with the FCC to C (by specifying the compiler subcommand fli tc on most UNIX systems; see Appendix A for exceptions).

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    compil<eol>

    MAINSAIL (R) Compiler
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.


    compile (? for help): callc.msl<eol>
    Opening intmod for $SYS...

    callc.msl 1 ...

    Objmod for CALLC on callc-xxx.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): <eol>
    *
    <eol>

    (control returns to the UNIX shell)

  2. Make a new MAINSAIL bootstrap that declares MSTOC to be a foreign MODULE. The foreign MODULE names must be uppercase on all current flavors of UNIX. UNIX assemblers are case-sensitive.

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    conf<eol>
    MAINSAIL (R) Bootstrap Configurator
    Restoring configuration values from file

        
    /usr/mainsail/16.20.1/xxx.cnf
    CONFbootfilename fcc.s<eol>
    CONFforeignmodules<eol>
    FOREIGNMODULES is
    ...
    Should be:
    =<eol>
    MSTOC<eol>
    <eol>
    CONF<eol>
    Bootstrap written in file fcc.s
    *
    <eol>

    (control returns to the UNIX shell)

  3. Compile the C code with the C compiler.

    cc -c cproc.c<eol>

  4. Assemble and link the new MAINSAIL bootstrap. The commands shown are typical of some UNIX flavors, but do not apply to all UNIX flavors. Consult Appendix B for details about how to make MAINSAIL bootstraps.

    cc -o fcc /usr/mainsail/16.20.1/m.o fcc.s mstoc.s cproc.o<eol>

  5. Run the new executable MAINSAIL bootstrap and call the foreign procedure.

    fcc<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    callc<eol>

10.6. MAINSAIL Entry Compiler Example

Suppose that the C procedure callms is to call the MAINSAIL PROCEDURE proc1. Figures 10–7, 10–8, 10–9, and 10–10 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. Example 10–11 shows how to compile and run callms.

Figure 10–7. C Procedure That Calls MAINSAIL PROCEDURE proc1
C program (in file callms.c):

callms ()
{
/*  
MAINSAIL proc1 does the following:
    (1) 
Adds its first two arguments and returns
        
the result
    (2) 
Sets bo to be TRUE
*/
short bo;
int result,li1,li2;
bo = 0; li1 = 1; li2 = 2;
result = proc1(li1,li2,&bo);
printf("Result is %d\n",result);
if (bo == 0) {printf("FAILUREbo should be nonZero\n");}
}

Figure 10–8. MAINSAIL MODULE MSMOD Called by C Procedure callms
MAINSAIL MODULE MSMOD (in file msmod.msl):

BEGIN "msMod"

MODULE msMod (
    
$CINT PROCEDURE proc1 (
        
$CINT                           li1,li2;
        
PRODUCES BOOLEAN($shortSize)    bo);
or, before Version 16.29, declare proc1 this way:
    
LONG INTEGER PROCEDURE proc1 (
        
LONG INTEGER        li1,li2;
        
PRODUCES BOOLEAN    bo);
    );

$CINT PROCEDURE proc1 (
    
$CINT                           li1,li2;
    
PRODUCES BOOLEAN($shortSize)    bo);
or, before Version 16.29, declare proc1 this way:
LONG INTEGER PROCEDURE proc1 (
    
LONG INTEGER        li1,li2;
    
PRODUCES BOOLEAN    bo);
BEGIN
bo := TRUE;
RETURN(li1 + li2);
END;

END "msMod"

Figure 10–9. MAINSAIL Foreign Language Interface MODULE MSTOC
MAINSAIL MODULE MSTOC (in file mstoc.msl):

BEGIN "msToC"

MODULE msToC (PROCEDURE callMs);

PROCEDURE callMs;;

END "msToC"

Figure 10–10. MAINSAIL MODULE CALLC That Calls C Procedure callms
MAINSAIL MODULE CALLC (in file callc.msl):

BEGIN "callC"

MODULE msToC (PROCEDURE callMs);

INITIAL PROCEDURE;
callMs;

END "callC"

Example 10–11. C to MAINSAIL Example
  1. Compile MSMOD and CALLC with the UNIX MAINSAIL compiler. Compile MSMOD with the MEC from C (by specifying the compiler subcommand fli fc). Compile MSTOC with the FCC to C (by specifying the compiler subcommand fli tc). The subcommands fli fc and fli tc may be different on some UNIX flavors; see Appendix A.

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    compil<eol>

    MAINSAIL (R) Compiler
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.


    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>

    (control returns to the UNIX shell)

  2. Make a new MAINSAIL bootstrap that declares MSTOC to be a foreign MODULE. The foreign MODULE names must be uppercase on all current flavors of UNIX. UNIX assemblers are case-sensitive.

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    conf<eol>
    MAINSAIL (R) Bootstrap Configurator
    Restoring configuration values from file

        
    /usr/mainsail/16.20.1/xxx.cnf
    CONFbootfilename mec.s<eol>
    CONFforeignmodules<eol>
    FOREIGNMODULES is
    ...
    Should be:
    =<eol>
    MSTOC<eol>
    <eol>
    CONF<eol>
    Bootstrap written in file mec.s
    *
    <eol>

    (control returns to the UNIX shell)

  3. Compile the C code with the C compiler.

    cc -c callms.c<eol>

  4. Assemble and link the new MAINSAIL bootstrap. The commands shown are typical of some UNIX flavors, but do not apply to all UNIX flavors. Consult Appendix B for details about how to make MAINSAIL bootstraps.

    cc -o mec /usr/mainsail/16.20.1/m.o mec.s msmod.s mstoc.s callms.o<eol>

  5. Run the new executable MAINSAIL bootstrap and call the foreign procedure.

    mec<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    callc<eol>
    Result is 3
    *
    <eol>

10.7. Entry FLI Example When Foreign Code Starts Execution

It is currently possible on every supported flavor of UNIX for a C main program to begin execution and then call MAINSAIL; that is, the function main can reside in foreign code, rather than being a part of the m.o file on the MAINSAIL directory that is linked with a MAINSAIL bootstrap when MAINSAIL starts execution instead of foreign code.

In order for foreign code to start execution, you must build the bootstrap slightly differently from the way shown in Example 10–11:

For example, assume that the function callms in the file callms.c of Figure 10–7 is renamed to main, and the file itself is renamed to main.c, as shown in Figure 10–12.

Figure 10–12. C Program with Function main That Calls MAINSAIL PROCEDURE proc1
C program (in file main.c):

main ()
{
/*  
MAINSAIL proc1 does the following:
    (1) 
Adds its first two arguments and returns
        
the result
    (2) 
Sets bo to be TRUE
*/
short bo;
int result,li1,li2;
bo = 0; li1 = 1; li2 = 2;
result = proc1(li1,li2,&bo);
printf("Result is %d\n",result);
if (bo == 0) {printf("FAILUREbo should be nonZero\n");}
}

To link a bootstrap named main that calls proc1 in the MODULE MSMOD of Figure 10–8, follow the example shown in Example 10–13 (adapting the example as necessary for your platform; see Appendix A).

Example 10–13. C to MAINSAIL Example When Foreign Code Starts Execution
  1. Compile MSMOD with the UNIX MAINSAIL compiler. Compile MSMOD with the MEC from C (by specifying the compiler subcommand fli fc). The subcommand fli fc may be different on some UNIX flavors; see Appendix A.

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    compil<eol>

    MAINSAIL (R) Compiler
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.


    compile (? for help): msmod.msl<eol>
    Opening intmod for $SYS...

    msmod.msl 1 ...

    compile (? for help): =,<eol>
    >
    fli fc<eol>
    >
    <eol>
    Opening intmod for $SYS...

    msmod.msl 1 ...

    compile (? for help): <eol>
    *
    <eol>

    (control returns to the UNIX shell)

  2. Make a new MAINSAIL bootstrap that sets the $foreignCodeStartsExecution ('H8) CONFIGURATIONBITS bit.

    mainsa<eol>
    MAINSAIL (R) Version 16.20.<release> (? for help)
    Revision: <date>
    Copyright (c) 1984-1998 by XIDAK, Inc., Point Arena,
     California, USA.

    *
    conf<eol>
    MAINSAIL (R) Bootstrap Configurator
    Restoring configuration values from file

        
    /usr/mainsail/16.20.1/xxx.cnf
    CONFbootfilename mecf.s<eol>
    CONFconfigurationbits !='H8<eol>
    CONF<eol>
    Bootstrap written in file mecf.s
    *
    <eol>

    (control returns to the UNIX shell)

  3. Compile the C code with the C compiler.

    cc -c main.c<eol>

  4. Assemble and link the new MAINSAIL bootstrap. The commands shown are typical of some UNIX flavors, but do not apply to all UNIX flavors. Consult Appendix B for details about how to make MAINSAIL bootstraps.

    cc -o main /usr/mainsail/16.20.1/f.o mecf.s msmod.s main.o

  5. Run the new executable MAINSAIL bootstrap and call the foreign procedure.

    main<eol>
    Result is 3

10.8. Caveat: Use of gets or fgets on stdin on UNIX

On UNIX, when MAINSAIL code is linked with C code, and the program's standard input is redirected to a disk file, you should not use gets or fgets in the C code to read from the standard input. You should instead use the UNIX functions read and write, and avoid reading more from the file than the number of lines your program actually needs.

The problem is that when MAINSAIL reads from standard input, it never reads more than one line (up to the next newline character), regardless of whether standard input is a terminal or a disk file. The implementation of gets and fgets, however, reads only a single line of input from a terminal, but reads enough to fill up a fixed-size buffer when reading from a disk file. This buffer is inaccessible to MAINSAIL. After C does a gets or fgets on stdin, MAINSAIL acts as if the unprocessed text up to the end of C's buffer is missing from the file.

A solution to the problem is to use something like the following function mygets instead of gets to read from standard input:

#include <stdio.h>
#
define cr 13
#
define fdStdin  0
#
define fdStdout 1

char *mygets(bufchar *buf;
{
char c;
int in;
char *b = buf;

if (isatty(fdStdin)) return gets(buf);  /* gets works for tty */

/*  
Simulate reading a line from the input file or pipe by
 *  
reading one character at-a-time.
 */

for (n = 0; ;) {
    
if ((i = read(fdStdin,&c,1)) < 0 )
        
return NULL;        /* documented gets() behavior */
    
if (!ibreak;
    
n++;
    
if ( c == '\n' ) break; /* discard newline */
    *
b++ = c;
    }
if (!nreturn NULL;    /* documented gets() behavior */
*
b++ = '\0';            /* NUL-terminate the result */
return buf;
}

10.9. Linking X Code with MAINSAIL

Some MAINSAIL bootstraps on UNIX can be used to invoke Motif-based tools, such as a GUI for MAINDEBUG and several graphical statistics-gathering and performance-analysis tools.

It is possible to link C or C++ code that calls X with a MAINSAIL bootstrap that also calls X. In order to do this, you need to make some changes to your C code, and you need to link in an additional file from the MAINSAIL directory.

10.9.1. Changes to C Code

If you wish to link C or C++ code that calls X routines with a MAINSAIL bootstrap that may also call X routines, then to avoid initializing X twice (which the X routines do not expect and do not handle correctly), your C/C++ program should call:

#include <xinit1ce.h>
...
xtAppInitializeJustOnce(...);

(note the initial lowercase x in xtAppInitializeJustOnce) instead of the standard X Toolkit initialization function XtAppInitialize (or any other X Toolkit initialization function, e.g., XtToolkitInitialize). xtAppInitializeJustOnce takes exactly the same parameters as XtAppInitialize, but if it has already been called, it returns the same value (and sets app_context_return to the same value) as when it was called the first time. Later calls to xtAppInitializeJustOnce do not parse or modify the argv_in_out, fallback_resources, or args arguments.

MAINSAIL always initializes the X Toolkit using xtAppInitializeJustOnce instead of XtAppInitialize.

The include file xinit1ce.h resides on the MAINSAIL directory. To compile a file that includes it, include the -I switch on the command line to the C compiler, specifying the MAINSAIL directory as an argument, e.g.:

-I/usr/mainsail/16.20.1

xinit1ce.h includes some additional .h files on the MAINSAIL directory; you cannot copy just the file xinit1ce.h to some other directory and expect the instructions to work.

You may use xtAppInitializeJustOnce in applications that are not linked with MAINSAIL. The file xinit1ce.c on the MAINSAIL directory contains the implementation of xtAppInitializeJustOnce; just link the output from this file in with your C program.

10.9.2. Building a MAINSAIL Bootstrap That Calls X Routines from MAINSAIL

When you build a MAINSAIL bootstrap that calls X routines from MAINSAIL (e.g., to run the MAINSAIL Motif-based tools), then when you run CONF, you need to restore from the CONF parameters file that contains the appropriate FOREIGNMODULES command. This file is located on the MAINSAIL directory; its file name is:

platformAbbreviationm.cnf

e.g., sun4m.cnf.

When you link such a bootstrap, you need to include the file x.o (also located on the MAINSAIL directory) in your final cc or ld command line in addition to the usual m.o or f.o file.

If you link in the x.o file, you do not need to compile xinit1ce.c explicitly as part of your bootstrap, since x.o includes the output from xinit1ce.c.

On all platforms, you will need to link the standard X and Motif C libraries with your bootstrap; the usual cc switches to do this are:

-lXm -lXt -lX11

On some platforms, you must specify additional cc switches to link in additional C libraries when you build an X bootstrap (these are in addition to the libraries usually specified when you build a MAINSAIL bootstrap for that platform):

Platform cc Switches for X
hppa -lPW
hppa64 -lXp -lICE -lSM -lXext

10.9.2.1. Setup of X/Motif Libraries on HPPA64
On HPPA64, file system links for the libraries for X and Motif may need to be set up before you install MAINSAIL, if you plan to use the Motif-based MAINSAIL tools or create MAINSAIL bootstraps that make X calls.

On the HP-UX system XIDAK used to develop the HPPA64 port, the /usr/lib directory (where many of the 32-bit libraries are stored) contained links to the appropriate X and Motif libraries on other directories, but there were no corresponding links in /usr/lib/pa20_64, the directory for 64-bit libraries. XIDAK therefore set up links in /usr/lib/pa20_64 that point to the 64-bit X and Motif libraries needed by the MAINSAIL Motif-based tools.

If you wish to use the MAINSAIL Motif-based tools on HPPA64, we recommend that you set up links in /usr/lib/pa20_64 as follows, if such links are not already present:

Link Name Actual Library
libXt.a /usr/lib/X11R6/pa20_64/libXt.3
libX11.a /usr/lib/X11R6/pa20_64/libX11.3
libXp.a /usr/lib/X11R6/pa20_64/libXp.2
libICE.a /usr/lib/X11R6/pa20_64/libICE.2
libSM.a /usr/lib/X11R6/pa20_64/libSM.2
libXext.a /usr/lib/X11R6/pa20_64/libXext.3
libXm.a /usr/lib/Motif2.1/pa20_64/libXm.4

If you do not set up the links, the standard MAINSAIL installation script ihppa64.com will fail to find the X/Motif libraries needed to build the mainsam bootstrap. (You may set up the links in some directory other then /usr/lib/pa20_64, but then you will need to use the -xl, -xtl, or -xml switch to ihppa64.com; see the installation notes for HPPA64 for details.)

In each case, the “actual library” listed above is the library that had the highest-numbered suffix on the HPPA64 development machine used by XIDAK; if newer versions of the same libraries come out, you will probably want to substitute them for the names shown above.

10.9.2.2. X/Motif on Linux
MAINSAIL in conjunction with X and Motif has not been tested on LINIA64 or LINPN, so Motif-related facilities and Motif-based tools are not available on those platforms.

10.10. Passing Command Line Arguments from C to MAINSAIL When Foreign Code Starts Execution: UNIX-Specific Function xiSetArgvForMainsail

On UNIX, the C function xiSetArgvForMainsail allows you to pass command line arguments from C to MAINSAIL in bootstraps where foreign code starts execution.

The UNIX-specific function xiSetArgvForMainsail takes a single char** argument:

void xiSetArgvForMainsail (char **argv)

xiSetArgvForMainsail passes the argv argument (e.g., as passed to the C main function) to MAINSAIL. argv is terminated by a zero char pointer.

When C starts execution in a MAINSAIL bootstrap, MAINSAIL has no way to get a hold of argv unless you call xiSetArgvForMainsail to pass the argv value to MAINSAIL. If argv is not set, MAINSAIL will not have a value for $programName or be able to see the operating system's command line arguments.

Calling xiSetArgvForMainsail is not useful when MAINSAIL starts execution.

In C source files that call xiSetArgvForMainsail, include the header file ximslargv.h on the MAINSAIL directory with:

#include <ximslargv.h>

To compile a file that includes ximslargv.h, include the -I switch on the command line to the C compiler, specifying the MAINSAIL directory as an argument, e.g.:

-I/usr/mainsail/16.20.1

ximslargv.h includes some additional .h files on the MAINSAIL directory; you cannot copy just the file ximslargv.h to some other directory and expect the instructions to work.


previous   next   top   contents   index   framed top   this page unframed

MAINSAIL System-Specific User's Guides, Chapter 10