Previous Next Contents Index Doc Set Home


The FORTRAN-Pascal Interface

8


This chapter describes how to mix FORTRAN 77 and Pascal modules in the same program. It contains the following sections:

Compiler Mixed-Language Programs

page 167

Compatibility of Types for FORTRAN and Pascal

page 168

General Parameter-Passing in FORTRAN and Pascal

page 171

Procedure Calls: FORTRAN-Pascal

page 172

Procedure Calls: Pascal-FORTRAN

page 189

Routines as Parameters

page 206


Compiler Mixed-Language Programs

When you compile with the -v (verbose) option, the Pascal driver brings in the runtime libraries for the main module.

However, when you compile a module that is not the main module, and which is written in a language different from the main module, you must explicitly bring in the runtime library on the command-line.

For example, you must use the compiler options -lpfc and -lpc when you compile a FORTRAN main routine that calls Pascal. The -lpfc option links the common startup code for programs containing mixed Pascal and FORTRAN object libraries. The -lpc option includes the Pascal object library, libpc.

Specify -lpfc on the command-line before -lpc. For example:

hostname% pc -c my_pascal.p
hostname% f77 my_pascal.o my_fortran.f -lpfc -lpc
Sampmain.f:
 MAIN:

The -c option to pc produces an unlinked object file.

When you compile a Pascal main routine that calls FORTRAN, you must use the compiler options -lpfc and -lF77. The -lF77 option links the FORTRAN object library, libf77.

You must specify -lpfc on the command-line before -lF77. For example:

hostname% f77 -c my_fortran.f
hostname% pc my_fortran.o my_pascal.p -lpfc -lF77
my_fortran.f:
    MAIN:

You can omit the libraries if the foreign language module does not interact with the runtime environment, that is, it does no I/O, memory allocation, and so on. However, there is no overhead to linking to an unused library; therefore, always link in the appropriate runtime libraries, even if you think you may not need them.


Compatibility of Types for FORTRAN and Pascal

Table 8-1 lists the default sizes and alignments of compatible types for FORTRAN and Pascal.

Table  8-1 Default Sizes and Alignments of Compatible Types (Pascal and FORTRAN)

Pascal Type
FORTRAN Type
Size (Bytes)
Alignment (Bytes)

double

double precision

8

8

longreal

double precision

8

8

real

double precision

8

8

single

real

4

4

shortreal

real

4

4

integer16

integer*2

2

2

integer32

integer*4

4

4

integer

integer*4

4

4

-128..127

logical*1, byte, or character

1

1

boolean

logical*1, byte, or character

1

1

alfa

character*10

10

1

char

character

1

1

string

character*80

80

1

varying[n]

of char

structure /v/ integer*4 character*n

end structure

-

4

array

array

Same as element type

record

structure

-

4

Table 8-2 lists the default sizes and alignments of compatible types for FORTRAN and Pascal with the -xl option:

Table  8-2 Sizes and Alignments of Compatible Types (Pascal and FORTRAN) with -xl-

Pascal Type
FORTRAN Type
Size (Bytes)
Alignment (Bytes)

real

real

4

4

integer

integer*2

2

2

Precautions with Compatible Types

This section describes the precautions you must take when working with character strings and array indexes.

Character Strings

There are some precautions to take with character strings regarding the null byte, passing by value, and static storage:

Array Indexes

The Pascal and FORTRAN array indexes can start at any integer; be sure they match.

Incompatibilities

There are several incompatibilities between Pascal and FORTRAN variant records, enumerated types, and set types.

Variant Records

In general, Pascal variant records require adjustment of alignment to match with FORTRAN unions and structures.

Enumerated Types

Pascal enumerated types have no comparable type in FORTRAN.

Pascal Set Types

In Pascal, a set type is implemented as a bit vector, which is similar to a FORTRAN 16-bit word. Direct access to individual elements of a set is highly machine-dependent and should be avoided.

Multidimensional Arrays

Pascal multidimension arrays are incompatible with FORTRAN multi-dimension arrays. Since Pascal arrays use row-major indexing, and FORTRAN arrays use column-major indexing, an array passed in either direction appears to be transposed.


General Parameter-Passing in FORTRAN and Pascal

A few general rules apply to passing parameters:


Procedure Calls: FORTRAN-Pascal

Here are examples of how a FORTRAN main program calls a Pascal procedure.

The Pascal procedure, Samp.p. Note the procedure definition. The procedure name in the procedure statement is in lowercase with a trailing underscore (_). This format is required to match the conventions of the FORTRAN compiler. var parameters are used to match

FORTRAN defaults.

procedure samp_(var i: integer; var r: real);

begin
    i := 9;
    r := 9.9
end; { samp_ }

The FORTRAN main program, Sampmain.f. Note the procedure declaration and call. FORTRAN converts to lowercase by default; you do not explicitly give the underscore (_).

integer i
        double precision  d

        call Samp ( i, d )
        write( *, '(I2, F4.1)')  i, d
        stop
        end

The commands to compile and execute Samp.p and Sampmain.f

hostname% pc -c Samp.p
hostname% f77 Samp.o Sampmain.f -lpfc -lpc
Sampmain.f:
 MAIN:
hostname% a.out
 9 9.9

Variable Parameters

Pascal passes all var parameters by reference, FORTRAN's default.

Simple Types without the -xl Option

With var parameters, simple types match.

See the following example:

The Pascal procedure, SimVar.p

procedure simvar_(var t, f: boolean; var c: char;
                  var i: integer; var r: real;
                  var si: integer16; var sr: shortreal);

begin
    t := true;
    f := false;
    c := 'z';
    i := 9;
    r := 9.9;
    si := 9;
    sr := 9.9
end; { simvar_ }

The FORTRAN main program, SimVarmain.f

        logical*1         t, f
        character         c
        integer*4         i
        double precision  d
        integer*2         si
        real              sr

        call SimVar ( t, f, c, i, d, si, sr )

        write(*, "(L2,L2,A2,I2,F4.1,I2,F4.1)")
        &                  t, f, c, i, d,   si,sr
        stop
        end

The commands to compile and execute SimVar.p and SimVarmain.f

hostname% pc -c SimVar.p
hostname% f77 SimVar.o SimVarmain.f -lpfc -lpc
SimVarmain.f:
 MAIN:
hostname% a.out
 T F z 9 9.9 9 9.9

Simple Types with the -xl Option

When you pass the -xl option, the Pascal data type real must be paired with a FORTRAN data type real; the Pascal data type integer must be paired with a FORTRAN data type, integer*2.

Strings of Characters

The FORTRAN counterpart to the Pascal alfa and string types is a character string, and the FORTRAN counterpart to the Pascal varying is a structure. By default, FORTRAN, passes all by reference:

The Pascal procedure, StrVar.p

type
    varstr = varying [25] of char;
 
procedure strvar_(var a: alfa; var s: string;
                  var v: varstr);

begin
    a := 'abcdefghij';
    s := 'abcdefghijklmnopqrtstuvwxyz';
    v := 'oyvay'
end; { strvar_ }

The FORTRAN main program, StrVarmain.f

           structure /VarLenStr/
           integer   nbytes
           character a*25
        end structure
        record /VarLenStr/ vls
        character s10*10, s80*80, s25*25
        vls.nbytes = 0
        Call StrVar( s10, s80, vls )
        s25(1:5) = vls.a(1:vls.nbytes)
        write (*, 1) s10, s80, s25
 1      format("s10='", A, "'",
&            / "s80='", A, "'",
&            / "s25='", A, "'"  )
        end

The commands to compile and execute StrVar.p and StrVarmain.f

hostname% pc -c StrVar.p
hostname% f77 StrVar.o StrVarmain.f -lpfc -lpc
StrVarmain.f:
    MAIN:
hostname% a.out
s10='abcdefghij'
s80='abcdefghijklmnopqrtstuvwxyz
s25='oyvay'

Fixed Arrays

For a fixed array parameter, pass the same type and size by reference, as shown in the following example:

The Pascal procedure, FixVec.p

type
    VecTyp = array [0..8] of integer;
 
procedure fixvec_(var V: VecTyp; var Total: integer);

var
    i: integer;

begin
    Total := 0;
    for i := 0 to 8 do 
      Total := Total + V[i]
end; { fixvec_ }

The FORTRAN main program, FixVecmain.f

        integer Sum
        integer a(9)
        data    a / 1,2,3,4,5,6,7,8,9 /
        call FixVec ( a, Sum )
        write( *, "( I3 )")  Sum
        stop
        end

The commands to compile and execute FixVec.p and FixVecmain.f

hostname% pc -c FixVec.p
hostname% f77 FixVec.o FixVecmain.f -lpfc -lpc
hostname% a.out
FixVecmain.f:
 MAIN:
	45

The univ Arrays

You can pass any size array to a Pascal procedure expecting a univ array, but there is no advantage in doing so, since there is no type or size checking for separate compilations. However, if you want to use an existing Pascal procedure that has a univ array, you can do so. All univ arrays that are in, out, in out, or var parameters pass by reference.

The Pascal procedure, UniVec.p, which defines a 10-element array

type
    VecTyp = array [0..9] of integer;

procedure univec_(in V:univ VecTyp; var Last: integer;
                  var Total: integer);

var
    i: integer;

begin
    Total := 0;
    for i := 0 to Last do 
      Total := Total + V[i]
end; { univec_ }

The FORTRAN main program, UniVecmain.f, which passes a 3-element array to the Pascal procedure written to do a 10-element array

        integer  Sum
        integer a(0:2)
        data    a / 7, 8, 9 /
        call UniVec ( a, 2, Sum )
        write( *, "( I3 )")  Sum
        stop
        end

The commands to compile and execute UniVec.p and UniVecmain.f

hostname%  pc -c UniVec.p
hostname% f77 UniVec.o UniVecmain.f -lpfc -lpc
UniVecmain.f:
    MAIN:
hostname% a.out
 24

Conformant Arrays

For conformant arrays, with single-dimension array, pass upper and lower bounds, placed after the declared parameter list, as in:

function ip(var x:array[lb..ub:integer] of real):real;
	 ...

double precision v1(10)
double precision z
z = ip ( v1, %VAL(0), %VAL(9) )
...

Pascal passes the bounds by value, so FORTRAN must pass them by value, too.

One bounds pair may apply to several arrays if they are declared in the same parameter group:

function ip(var x,y:array[lb..ub:integer] of real):real;
	...

double precision v1(10), v2(10)
double precision z
z = ip ( v1, v2, %VAL(0), %VAL(9) )
 	...

Examples of single-dimension array and array of character conformant arrays follow. Conformant arrays are included here only because they are a relatively standard feature; there are usually more efficient and simpler ways to do that.

Example 1: Single-Dimension Array

The Pascal procedure, IntCA.p. Pascal passes the bounds by value.

procedure intca_(var a: array [lb..ub: integer] of integer);

begin
    a[1] := 1;
    a[2] := 2
end; { intca_ }

The FORTRAN main program, IntCAmain.f

        integer k
        integer s(0:2)
        data    s  / 0, 0, 0 /
        call IntCA ( s, %VAL(0), %VAL(2) )
        do k = 0, 2
        write( *, "(I1)" )  s(k)
        end do
        stop
        end

The commands to compile and execute IntCA.p and IntCAmain.f

hostname% pc -c IntCA.p
hostname% f77 IntCA.o IntCAmain.f -lpfc -lpc
IntCAmain.f:
 MAIN:
hostname% a.out
0
1
2

Example 2: Array of Characters

The Pascal procedure, ChrCA.p. Pascal passes the bounds by value.

procedure chrca_(var a: array [lb..ub: integer] of char);

begin
    a[0] := 'T';
    a[13] := 'o'
end; { chrca_ }

The FORTRAN main program, ChrCAmain.f

        character s*16
        data  s / "this is a string" /
        call ChrCA( s, %VAL(0), %VAL(15) )
        write( *, "(A)" )  s
        stop
        end

The commands to compile and execute ChrCA.p and CharCAmain.f

hostname% pc -c ChrCA.p
hostname% f77 ChrCA.o ChrCAmain.f -lpfc -lpc
ChrCAmain.f:
   MAIN:
hostname% a.out
This is a string

Records and Structures

In most cases, a Pascal record describes the same objects as its FORTRAN structure equivalent, provided that the components have compatible types and are declared in the same order. The compatibility of the types depends mostly on size and alignment.

For more information, see "Compatibility of Types for FORTRAN and Pascal" on page 168.

A Pascal record of an integer and a character string matches a FORTRAN structure of the same. Consider these examples:

The Pascal procedure,
StruChr.p

type
    lenstr = 
      record
          nbytes: integer;
          chrstr: array [0..25] of char
      end;

procedure struchr_(var v: lenstr);

begin
    v.chrstr := 'oyvay';
    v.nbytes := 5
end; { struchr_ }

The FORTRAN main program, StruChrmain.f

        structure /VarLenStr/
           integer   nbytes
           character a*25
        end structure
        record /VarLenStr/ vls
        character s25*25
        vls.nbytes = 0
        Call StruChr( vls )
        s25(1:5) = vls.a(1:vls.nbytes)
        write ( *, 1 )  s25
 1      format("s25='", A, "'" )
        stop
        end

The commands to compile and execute Struchr.p and StruChrmain.f

hostname% pc -c StruChr.p
hostname% f77 StruChr.o StruChrmain.f -lpfc -lpc
StruChrmain.f:
   MAIN:
hostname% a.out
s25='oyvay'

Variant Records

FORTRAN equivalents of variant records can sometimes be constructed, although there is some variation with architecture, and sometimes you need to adjust the alignment.

The Pascal procedure,
VarRec.p

type vr = record
    case tag: char of
        'a': ( ch1, ch2: char ) ;
        'b': ( flag: boolean ) ;
        'K': ( ALIGN: integer ) ;
    end ;

procedure varrec_ ( var Rec: vr ) ;

begin
    if ( Rec.ch1 = 'a' )
        then Rec.ch2 := 'Z'
end; { VarRec.p }

The FORTRAN main program, VarRecmain.f. The variable ALIGN is integer*2, and is needed to match the Pascal variant record layout.

        structure /a_var/
                character ch1, ch2
        end structure
        structure /b_var/
                character flag
        end structure
        structure /c_var/
                integer*2 ALIGN
        end structure
        structure /var_part/
                union
                   map
                        record /a_var/ a_rec
                   end map
                   map
                        record /b_var/ b_rec
                   end map
                   map
                        record /c_var/ c_rec
                   end map
                end union
        end structure
        structure /vrnt/
                character tag
                record /var_part/ var_rec
        end structure
        record /vrnt/ VRec
        VRec.var_rec.a_rec.ch1 = 'a'
        VRec.var_rec.a_rec.ch2 = 'b'
        call varrec ( VRec )
        write ( *, * )  VRec.var_rec.a_rec.ch2
        stop
        end

The commands to compile and execute VarRec.p and VarRecmain.f without -xl

hostname% pc -c VarRec.p
hostname% f77 VarRec.o VarRecmain.f
VarRecmain.f:
   MAIN:
hostname% a.out
b

Pascal Set Type

The Pascal set type is incompatible with FORTRAN.

Pascal intset Type

The Pascal intset type is predefined as set of [0..127]. A variable of this type takes a minimum of 16 bytes of storage.

The Pascal procedure, IntSetVar.p, which has an intset of the elements
[1, 3, 7, 8]

procedure intsetvar_(var s: intset);

begin
    s := [1, 3, 7, 8]
end; { intsetvar_ }

The FORTRAN main program, IntSetVarmain.f

		integer*2 s(8)
        pointer ( ps, s )
        ps = malloc(16)
        call IntSetVar ( s )
        do  i = 5, 8
           write( *, 1 )  s(i), i
        end do
 1      format(o3,1x, 'octal   (word', i2, ')')
        write( *, "('110 001 010 (binary, word 8)')")
        write( *, "('876 543 210 (bit nos, word 8)')")
        stop

The commands to compile and execute IntSetVar.p and IntSetVarmain.f. The output of this example depends on the architecture of your machine.

hostname% pc -c IntSetVar.p
hostname% f77 IntSetVar.o IntSetVarmain.f -lpfc -lpc
IntSetVarmain.f:
  MAIN:
hostname% a.out
     0 octal          (word 5)
     0 octal          (word 6)
     0 octal          (word 7)
612 octal             (word 8)
110 001 010           (binary, word 8)
876 543 210           (bit nos, word 8)

Value Parameters

In general, Pascal passes value parameters on the stack.

Simple Types without the -xl Option

Without the -xl option, simple types match.

See the following example:

The Pascal procedure, SimVal.p. t, f, c, i, r, and s are value parameters.

procedure simval_(t, f: boolean; c: char; i: integer;
                  r: real; s: integer16; var reply: integer);

begin
    reply := 0;
    { If nth arg is ok, set nth octal digit to one. }
    if t then 
      reply := reply + 1;
    if not f then 
      reply := reply + 8;
    if c = 'z' then 
      reply := reply + 64;
    if i = 9 then 
      reply := reply + 512;
    if r = 9.9 then 
      reply := reply + 4096;
    if s = 9 then 
      reply := reply + 32768
end; { simval_ }

The FORTRAN main program, SimValmain.f

        logical*1							t, f
        character							c
        integer*4							i
        double precision							d
        integer*2							s
        integer*4							args
        data t / .true. /,  f / .false. /,  c / 'z' /
&            i / 9 /,       d / 9.9 /,      s / 9 /

        call SimVal( %VAL(t), %VAL(f), %VAL(c),
&                       %VAL(i), %VAL(d), %VAL(s), args )
        write( *, 1 )  args
 1      format('args=', o6, '(If nth digit=1, arg n OK)')
        stop
        end

The commands to compile and execute SimVal.p and SimValmain.f

hostname% pc -c SimVal.p
hostname% f77 SimVal.o SimValmain.f -lpfc -lpc
SimValmain.f:
   MAIN:
hostname% a.out
args=111111(If nth digit=1, arg n OK)

Simple Types with the -xl Option

With the -xl option, match Pascal real with FORTRAN real and Pascal integer with FORTRAN integer*2.

You can pass by value using the %VAL() feature of FORTRAN.

Type shortreal

Unlike C, there is no problem with passing shortreal value parameters between Pascal and FORTRAN. They can be passed exactly as in the previous example, with the Pascal shortreal type matching the FORTRAN real type.

Arrays

Since FORTRAN cannot pass arrays by value, it cannot pass strings of characters, fixed arrays, or univ arrays by value.

Conformant Arrays

Although Pascal generally passes all value parameters on the stack, the exception is value-conformant array parameters, which are handled by creating a copy in the caller environment and passing a pointer to the copy. In addition, the bounds of the array must be passed. See "Conformant Arrays" on page 177.

This example is the same as the one in the earlier section, except that the var prefix is deleted.

Pascal procedure, ChrCAx.p

procedure chrca_ ( a: array [lb..ub:integer] of char) ;

begin
        a[0] := 'T' ;
        a[13] := 'o' ;
end; { chrca_ }

The FORTRAN main program, ChrCAmain.f

        character s*16
        data  s / "this is a string" /
        call ChrCA( s, %VAL(0), %VAL(15) )
        write( *, "(A)" )  s
        stop
        end

The commands to compile and execute ChrCAx.p and ChrCAmain.f

hostname% pc -c ChrCAx.p
hostname% f77 ChrCAx.o ChrCAmain.f -lpfc -lpc
ChrCAmain.f:
   MAIN:
hostname% a.out
This is a string

Pointers

Pointers are easy to pass, as shown in the following example:

The Pascal procedure, PassPtr.p. In the Pascal procedure statement, the name must be all in lowercase, with a trailing underscore (_).

type
    PtrInt  = ^integer ;
    PtrReal = ^real ;
procedure passptr_ ( var iPtr: PtrInt ;
                     var dPtr: PtrReal ) ;
begin
    iPtr^ := 9 ;
    dPtr^ := 9.9 ;
end ;

The FORTRAN main program, PassPtrmain.f. In the FORTRAN main program, the name is converted to lowercase. Uppsercase is ignored.

        program PassPtrmain
        integer          i
        double precision d
        integer          iptr, dptr
        pointer ( iPtr, i ), ( dPtr, d )
        iPtr = malloc( 4 )
        dPtr = malloc( 8 )
        i = 0 
        d = 0.0
        call PassPtr ( iPtr, dPtr )
        write( *, "(i2, f4.1)" )  i, d
        stop
        end

The commands to compile and execute PastPtr.p and PassPtrmain.f

hostname% pc -c PassPtr.p
hostname% f77 PassPtr.o PassPtrmain.f -lpfc -lpc
PassPtrmain.f:
   MAIN passptrmain:
hostname% a.out
9 9.9

Function Return Values

Function return values match types the same as with parameters, and they pass in much the same way. See "Procedure Calls: FORTRAN-Pascal" on page 172.

Simple Types

The simple types pass in a straightforward way, as follows:

The Pascal function, RetReal.p

function retreal_(var x: real): real;

begin
    retreal_ := x + 1
end; { retreal_ }

The FORTRAN main program, RetRealmain.f

        double precision r, s, RetReal
        r = 2.0
        s = RetReal( r )
        write( *, "(2f4.1)") r, s
        stop
        end

The commands to compile and execute RetReal.p and RetRealmain.f without -xl

hostname% pc -c RetReal.p
hostname% f77 RetReal.o RetRealmain.f -lpfc -lpc
RetRealmain.f:
   MAIN:
hostname% a.out
 2.0 3.0

Type shortreal

There is no problem with returning a shortreal function value between Pascal and FORTRAN. As in the previous example, it can be passed exactly, with the Pascal shortreal type matching the FORTRAN real type (without -xl).


Procedure Calls: Pascal-FORTRAN

This section parallels "Procedure Calls: FORTRAN-Pascal" on page 172. The comments and restrictions given in that section apply here, also.

Variable Parameters

Pascal passes all var parameters by reference, the FORTRAN default.

Simple Types

Simple types pass in a straightforward manner, as follows:

The FORTRAN subroutine, SimVar.f

        subroutine SimVar ( t, f, c, i, d, si, sr )
        logical*1        t, f
        character        c
        integer          i
        double precision d
        integer*2        si
        real             sr
        t = .true. 
        f = .false.
        c  = 'z'
        i  = 9
        d  = 9.9
        si = 9
        sr = 9.9
        return
        end

The Pascal main program, SimVarmain.p

program SimVarmain(output);

var
    t, f: boolean;
    c: char;
    i: integer;
    r: real;
    si: integer16;
    sr: shortreal;

procedure simvar(var t, f: boolean; var c: char; 
                 var i: integer; var r: real;
                 var si: integer16; var sr: shortreal);
                 external fortran;

begin
    simvar(t, f, c, i, r, si, sr);
    writeln(t, f: 6, c: 2, i: 2, r: 4: 1, si: 2, sr: 4: 1)
end. { SimVarmain }

The commands to compile and execute SimVar.p and SimVarmain.p

hostname% f77 -c SimVar.f
SimVar.f:
	simvar:
hostname% pc SimVar.o SimVarmain.p -lpfc -lF77
hostname% a.out
true false z 9 9.9 9 9.9

Strings of Characters

The alfa and string types pass simply; varying strings are a little tricky. All pass by reference.

The FORTRAN subroutine, StrVar.f

        subroutine StrVar ( s10, s80, vls )
        character   s10*10, s80*80
        structure /VarLenStr/
           integer  nbytes
           character a*25
        end structure
        record /VarLenStr/ vls
        character ax*10, sx*80, vx*5
        data ax  / "abcdefghij" /,
&          sx / "abcdefghijklmnopqrstuvwxyz" /,
&          vx / "oyvay" /
        s10(1:10) = ax(1:10)
        s80(1:80) = sx(1:80)
        vls.a(1:5) = vx(1:5)
        vls.nbytes = 5
        return
        end

The Pascal main program, StrVarmain.p

program StrVarmain(output);

type
    varstr = varying [25] of char;

var
    a: alfa;
    s: string;
    v: varstr;

procedure strvar(var xa: alfa; var xs: string;
                 var xv: varstr); external fortran;

begin
    strvar(a, s, v);
    writeln(a);
    writeln(s);
    writeln(v);
    writeln('length(v)= ', length(v): 2)
end. { StrVarmain }

The commands to compile and execute StrVar.f and StrVarmain.p

hostname% f77 -c StrVar.f 
StrVar.f: 
		strvar:
hostname% pc StrVar.o StrVarmain.p -lpfc -lF77
hostname% a.out
abcdefghij
abcdefghijklmnopqrstuvwxyz
oyvay
length(v)= 5

Character Dummy Arguments

When you call FORTRAN 77 routines with character dummy arguments from Pascal programs--that is, routines in which string arguments are specified as character*(*) in the FORTRAN source, there is no explicit analogue in Pascal.

So, if you try to simply pass an actual string and specify the FORTRAN routine as extern fortran, the program fails, because implementation of this type of arguments implies that the actual length of the string is implicitly passed as an extra value argument after the string pointer.

To specify this routine in Pascal, declare it as having two arguments: a VAR argument of string type for the string pointer, and an extra value argument of integer32 type for the string length.

It is incorrect to specify the routine as extern fortran because Pascal passes all arguments to FORTRAN routines by reference. Consequently, to pass this type of argument, you must:

The following example illustrates this method:

The Pascal program, sun.pas

program Test(input,output);
var
  s : string;

procedure mygrout_(var prompt :string; length :integer32); external;

begin
  writeln('Starting...');
  s := 'Trio Jeepy';
  mygrout_(s, 8);
  writeln('Ending...')
end.

The FORTRAN subroutine, mygrout.f

        subroutine MyGrout(N)
        character*(*)N
        write(6,*) N
        return
        end

The commands to compile and run this program

hostname% pc -g -c sun.pas
hostname% f77 -g sun.o mygrout.f -lpc
mygrout.f:
        mygrout:
hostname% a.out
Starting...
 Trio Jee
Ending...

Fixed Arrays

For a fixed-array parameter, pass the same type and size by reference:

The FORTRAN subroutine, FixVec.f

        subroutine FixVec ( V, Sum )
        integer Sum
        integer V(0:8)
        integer i
        Sum = 0
        do  2 i = 0, 8 
 2      Sum = Sum + V(i)
        return
        end

The Pascal main program, FixVecmain.p

program FixVecmain(output);

type
    VecTyp = array [0..8] of integer;

var
    V: VecTyp := [1, 2, 3, 4, 5, 6, 7, 8, 9];
    Sum: integer;

procedure fixvec(var XV: VecTyp; var XSum: integer);
    external fortran;

begin
    fixvec(V, Sum);
    writeln(Sum: 4)
end. { FixVecmain }

The commands to compile and execute FixVec.f and FixVecmain.p

hostname% f77 -c FixVec.f
FixVec.f:
	fixvec:
hostname% pc FixVec.o FixVecmain.p -lpfc -lF77
hostname% a.out
   45

The univ Arrays

The univ arrays that are in, out, in out, or var parameters pass by reference.

The FORTRAN subroutine, UniVec.f

        subroutine UniVec ( V, Last, Sum )
        integer V(0:2), Last, Sum, i
        Sum = 0
        do i = 0, Last
                Sum = Sum + V(i)
        end do
        return
        end

The Pascal main program, UniVecmain.p

program UniVec;

type
    VecTyp = array [0..9] of integer;

procedure univec(var V:univ VecTyp; in Last: integer;
                 var Sum: integer); external fortran;

var
    Sum: integer;
    V: array [0..2] of integer;

begin
    V[0] := 7;
    V[1] := 8;
    V[2] := 9;
    univec(V, 2, Sum);
    writeln(Sum)
end. { UniVec }

The commands to compile and execute UniVec.f and UniVecmain.p

hostname% f77 -c UniVec.f
UniVec.f:
	univec:
hostname% pc UniVec.o UniVecmain.p -lpfc -lF77
hostname% a.out
	24

Conformant Arrays

Pascal-conformant array parameters are not compatible if Pascal calls FORTRAN.

Records and Structures

Records and structures pass as follows:

The FORTRAN subroutine, StruChr.f

        subroutine StruChr ( vls )
        structure /VarLenStr/
           integer   nbytes
           character a*25
        end structure
        record /VarLenStr/ vls
        vls.a(1:5) = 'oyvay'
        vls.nbytes = 5
        return
        end

The Pascal main program, StruChrmain.p

program StruChrmain;

type
    lenstr = 
      record
          nbytes: integer;
          chrstr: array [0..25] of char
      end;

var
    v: lenstr;

procedure struchr(var v: lenstr);
    external fortran;

begin
    struchr(v);
    writeln('v.chrstr = "', v.chrstr, '"');
    writeln('v.nbytes =', v.nbytes: 2)
end. { StruChrmain }

The commands to compile and execute StruChr.f and StruChrmain.p

hostname% f77 -c StruChr.f
StruChr.f:
	 struchr: 
hostname% pc StruChr.o StruChrmain.p -lpfc -lF77
hostname% a.out 
v.chrstr = "oyvay"
v.nbytes = 5

Variant Records

You can construct FORTRAN equivalents of variant records. There is some variation with architecture, and sometimes you need to adjust the alignment.

Chapter 6, "The C-Pascal Interface," has an example that matches the following example.

The FORTRAN subroutine, VarRec.f. The variable ALIGN is integer*2 and is needed to match the Pascal variant record layout.

        subroutine VarRec ( VRec )
        structure /a_var/
                character ch1, ch2
        end structure
        structure /b_var/
                character flag
        end structure
        structure /c_var/
                integer*2 ALIGN
        end structure
        structure /var_part/
                union
                   map
                        record /a_var/ a_rec
                   end map
                   map
                        record /b_var/ b_rec
                   end map
                   map
                        record /c_var/ c_rec
                   end map
                end union
        end structure
        structure /vrnt/
                character tag
                record /var_part/ var_rec
        end structure
        record /vrnt/ VRec
        if ( VRec.var_rec.a_rec.ch1 .eq. 'a' )
&               VRec.var_rec.a_rec.ch2 = 'Z'
        return
        end

The Pascal main program, VarRecmain.p

program VarRecmain;

type
    vr =
      record
          case tag: char of
              'a': ( ch1, ch2: char );
              'b': ( flag: boolean );
              'K': ( ALIGN: integer )
      end;

var
    Rec: vr;

procedure varrec(var d: vr); external fortran;

begin
    Rec.tag := 'a';
    Rec.ch1 := 'a';
    Rec.ch2 := 'b';
    varrec(Rec);
    writeln(Rec.ch2)
end. { VarRecmain }

The commands to compile and execute VarRec.f and VarRecmain.p without -xl

hostname% f77 -c VarRec.f
VarRec.f:
	varrec:
hostname% pc VarRec.o VarRecmain.p -lpfc -lF77
hostname% a.out
b

Value Parameters

With external fortran on the procedure statement, Pascal passes value parameters as FORTRAN expects them.

Simple Types

With external fortran, the procedure name in the procedure statement and in the call must be in lowercase, with no underscore (_).

The FORTRAN subroutine, SimVal.f

        subroutine  SimVal( t, f, c, i, d, s, reply )
        logical*1        t, f
        character        c
        integer*4        i
        double precision d
        integer*2        s
        integer*4        reply
        reply = 0
        if ( t          ) reply = reply + 1
        if ( .not. f    ) reply = reply + 8
        if ( c .eq. 'z' ) reply = reply + 64
        if ( i .eq. 9   ) reply = reply + 512
        if ( d .eq. 9.9 ) reply = reply + 4096
        if ( s .eq. 9   ) reply = reply + 32768
        return
        end

The Pascal main program, SimValmain.p

program SimVal(output);

var
    t: boolean := true;
    f: boolean := false;
    c: char := 'z';
    i: integer := 9;
    r: real := 9.9;
    s: integer16 := 9;
    args: integer;

procedure simval(t, f: boolean; c: char; i: integer;
                 r: real; s: integer16; var reply: integer);
                 external fortran;

begin
    simval(t, f, c, i, r, s, args);
    writeln('args=', args: 6 oct, ' (If nth digit=1, arg n OK.)')
end. { SimVal }

The commands to compile and execute SimVal.f and SimValmain.p

hostname% f77 -c SimVal.f
SimVal.f:
	 simval:
hostname% pc SimVal.o SimValmain.p -lpfc -lF77
hostname% a.out
args=111111 (If nth digit=1, arg n OK.)

Pointers

Pointers are easy to pass, as shown in the following example:

The FORTRAN subroutine, PassPtr.f. In the FORTRAN subroutine, the name is converted to lowercase. Uppsercase is ignored.

      subroutine PassPtr ( iPtr, dPtr )
      integer          i
      double precision d
      pointer ( iPtr, i ), ( dPtr, d )
      i  = 9
      d  = 9.9
      return
      end

The Pascal main program, PassPtrmain.p. In the Pascal program, where it calls the FORTRAN subroutine, the name must be in lowercase.

program PassPtrmain;

type
    PtrInt = ^ integer;
    PtrReal = ^ real;

var
    i: integer := 0;
    r: real := 0.0;
    iP: PtrInt;
    rP: PtrReal;

procedure passptr(var xiP: PtrInt; var xrP: PtrReal);
    external fortran;

begin
    iP := addr(i);
    rP := addr(r);
    passptr(iP, rP);
    writeln(i: 2, r: 4: 1)
end. { PassPtrmain }

The commands to compile and execute PassPtr.f and PassPtrmain.p

hostname% f77 -c PassPtr.f
PassPtr.f:
	    passptr:
hostname% pc PassPtr.o PassPtrmain.p -lpfc -lF77
hostname% a.out
 9 9.9

Function Return Values

Function return values match types the same as with parameters, and they pass in much the same way.

Simple Types

The simple types pass in a straightforward way, as in this example:

The FORTRAN function, RetReal.f

double precision function retreal ( x )
 retreal = x + 1.0
 return
 end

The Pascal main program, RetRealmain.p

program retrealmain;

var
    r, s: real;

function retreal(x: real): real; external fortran;

begin
    r := 2.0;
    s := retreal(r);
    writeln(r: 4: 1, s: 4: 1)
end. { retrealmain }

The commands to compile and execute RetReal.f and RetRealmain.p

hostname% f77 -c RetReal.f
RetReal.f
	     retreal:
hostname% pc RetReal.o RetRealmain.p -lpfc -lF77
hostname% a.out
 2.0 3.0

Type shortreal

You can return a shortreal function value between Pascal and FORTRAN. Pass it exactly as in the previous example, with the Pascal shortreal type matching the FORTRAN real type (without -xl).


Routines as Parameters

If the passed procedure is a top-level procedure, write it as follows:

The FORTRAN subroutine, PassProc.f

    subroutine PassProc ( r, s, prcdr )
      real r, s
      external prcdr
      call prcdr ( r, s )
      return
    end

The Pascal main program, PassProcmain.p

program PassProcmain;

var
    a, b: real;

procedure passproc(var u: real; var v: real;
    procedure p(var r: real; var s: real));
    external fortran;

procedure AddOne(var x: real; var y: real);

begin
    y := x + 1
end; { AddOne }

begin
    a := 8.0;
    b := 0.0;
    passproc(a, b, AddOne);
    writeln(a: 4: 1, b: 4: 1)
end. { PassProcmain }

The commands to compile and execute PassProc.f and PassProcmain.p

hostname% f77 -c PassProc.f
PassProc.f
	   passproc
hostname% pc PassProc.o PassProcmain.p -lpfc -lF77
hostname% a.out
 8.0 9.0

If the procedure is not a top-level procedure, then you do not deal with how to pass it, because that requires allowing for the static link. A procedure or function passed as an argument is associated with a static link to its lexical parent's activation record.

When an outer block procedure or function is passed as an argument, Pascal passes a null pointer in the position normally occupied by the static link of the passed routine. So that procedures and functions can be passed to other languages as arguments, the static links for all procedure or function arguments are placed after the end of the conformant array bounds pairs, if any.

Routines in other languages can be passed to Pascal; a dummy argument must be passed in the position normally occupied by the static link of the passed routine. If the passed routine is not a Pascal routine, the argument is used only as a placeholder.


Previous Next Contents Index Doc Set Home