PowerAda Mapping Ada Data Types to Other Languages

From OC Systems Wiki!
< PowerAda:Interface to Other Languages
Revision as of 00:35, 25 April 2019 by imported>WikiVisor (Text replacement - ">" to ">")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


The mechanism used for passing parameters to an imported non-Ada subprogram depends on the type of the formal parameters:

  • Scalar types are always passed by value, as required by the Ada language, except for parameters passed to FORTRAN. FORTRAN parameters need to be passed by reference, as required by the FORTRAN language.

    Warning: Incorrect operations inside a FORTRAN subprogram can change the values of parameters you pass even in some cases where the data objects are declared as constants in Ada.

  • A SHORT_SHORT_INTEGER value occupies 1 byte.

  • A SHORT_INTEGER value occupies 2 bytes.

  • An INTEGER value occupies 4 bytes.

  • A BOOLEAN value occupies 1 byte.

  • A CHARACTER value occupies 1 byte.

  • An enumeration literal occupies the number of bytes required to hold the largest value in the enumeration type. The first literal in an enumeration type is always 0 unless you use a representation clause to set different values for the literals.

  • Floating-point parameters are passed by value. FLOAT parameters occupy 4 bytes and LONG_FLOAT parameters occupy 8 bytes.

  • Access types are always passed by value, as required by the Ada language, and occupy four bytes.

  • Composite parameters with size less than or equal to 32 bits and containing only 1 component are passed by value. All others are passed by reference. The parameter list contains the 4-byte address of the composite being passed.

When declaring a record type which will be passed to an external routine, the use of pragma Convention is recommended. The effect of this pragma is to prevent record elements from being rearranged. (The PowerAda compiler does this by default to minimize the space required for storing records.) The syntax of pragma Convention is:

pragma Convention([Convention =>] convention_identifier,
                  [Entity =>] local_name);

For example, an Ada declaration of a record type File_Record which would be passed to a C routine should be followed by:

pragma Convention( C, File_Record );

(Pragma Convention supersedes the LegacyAda implementation-dependent pragma Preserve_Layout. Preserve_Layout should no longer be used because it is not portable.)

Notes:

  1. You cannot pass unconstrained composite parameters to subprograms that are called through pragma Import.

  2. Because the Ada type-checking mechanism cannot examine code written in other languages, take special care to ensure that the interfaced procedure accesses the parameters using the correct offsets and alignment.

  3. To pass the address of an array type (such as a string) to an interfaced subprogram, do not use expressions like THE_STRING'ADDRESS. Instead simply pass the array object.

    If the interfaced subprogram's Ada specification requires System.Address rather than the string or array type itself, pass the address of the first element: S(S'First)'Address.

    Note that you should not use a formal parameter of an access type in an imported subprogram specification, because the value passed will be the address of bounds information and not of the first byte of the object itself as expected by the foreign routine. Write the specification using the designated type instead, or System.Address if it is a scalar that must be passed by reference.

  4. FORTRAN stores arrays in column-major order, while Ada stores them in row-major order. Thus only single-dimension arrays are directly accessible through the interface mechanism. To access multi-dimensional arrays, you must perform the transposition yourself.

  5. FORTRAN encodes the length of a string as part of the string itself. To pass a string to a FORTRAN subprogram, declare a record like the following, declare objects of that type initialized with the proper values, and pass the record objects as parameters.

    type FORTRAN_String_Record is record
    String_Length : integer;
    String_Data : string(LowerLimit..UpperLimit);
    end record;

Example

Assume we wish to pass two strings to a FORTRAN subprogram. The FORTRAN subprogram is:

subroutine print_strings(str1, str2)
   character str1*(*), str2*(*)
   write(6,*) str1, str2
   call exit
   end

Ada assumes the user wants all parameters in FORTRAN calls to be passed by reference.

FORTRAN also employs additional hidden parameters (for the unconstrained string given, address and length). Unfortunately the FORTRAN compiler assumes, for the unconstrained string given, the hidden length parameter to be passed by value.

This combination of assumptions conspires to make it impossible to interface Ada directly to the given FORTRAN data type.

A workaround would be to declare the foreign routine as convention C, construct the parameter list appropriate to the FORTRAN compiler's assumptions, and supply the FORTRAN routine to the linker rather than an actual C routine. For example, link the given FORTRAN code with the Ada routine below:

------------------------------------------
with SYSTEM; 
with TEXT_IO;
procedure PRAGMA_FORTRAN_TEST(
   COMMAND_LINE : in STRING)
is 
   STR_1   : STRING(1..45) := "String one";
   STR_2   : STRING(1..28) := "String two";
procedure PRINT_STRINGS(
   STR1 : SYSTEM.ADDRESS;
   STR2 : SYSTEM.ADDRESS;
   LEN1 : INTEGER;
   LEN2 : INTEGER);
PRAGMA IMPORT(C, Print_Strings);
   -- Actual body is coded in FORTRAN
BEGIN
   PRINT_STRINGS(
      STR_1(STR_1'FIRST)'ADDRESS,
      STR_2(STR_2'FIRST)'ADDRESS,
      STR_1'LENGTH,
      STR_2'LENGTH);
END Pragma_Fortran_Test;
-------------------------------------------