PowerAda Pragma Export

From OC Systems Wiki!
< PowerAda:Interface to Other Languages
Revision as of 02:08, 24 April 2019 by imported>WikiVisor
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


Pragma Export can be used to identify an Ada subprogram which is to be called from a non-Ada subprogram. Alternatively, pragma Export can be used to identify an Ada object which is to be accessed from a non-Ada subprogram.

Syntax

The syntax of the pragma is as follows:

pragma Export(
        [Convention =>] convention_identifier,
        [Entity =>] local_name
           [, [External_Name =>] string_expression]
           [, [Link_Name =>] string_expression]);

If you want to identify an overloaded subprogram using pragma Export, use a renaming declaration that introduces a new name for the subprogram. Apply pragma Export using this new name. The new name must not itself be overloaded.

The following rules apply to the placement of pragma Export in your program:

  • When naming a subprogram inside a compilation unit, this pragma must appear later in the same compilation unit and in the same immediately enclosing declarative region as the subprogram declaration. A subprogram body acts as an implicit subprogram declaration if there is no explicit declaration.
  • When naming a compilation unit subprogram, this pragma must appear after the subprogram declaration (implicit or explicit) in the same compilation as the subprogram declaration and before any subsequent compilation units.
  • When naming an object, this pragma must appear later in the same compilation unit and in the same immediately enclosing declarative region as the object declaration.

External_Name is an optional Ada string literal that identifies the external name to be used for the subprogram or object. If External_Name is specified for a subprogram, its first character should NOT be a period (.); the compiler will prepend the period if needed. If External_Name is not specified for a subprogram, the default is the simple name for the subprogram, in all lowercase. (This is the same as that generated by pragma Import in the absence of a user-supplied External_Name.) If External_Name is not specified for an object, the default is the simple name for the object, in all lowercase. It is recommended that you always specify a External_Name explicitly to ensure uniqueness: see "Description" below.

Description

For a subprogram, pragma Export creates a C compatible interface routine whose entry point symbol is the External_Name specified in the pragma (or generated by default). When a subprogram S has been Exported, S'ACCESS or S'ADDRESS yields the function descriptor of this interface routine. For an object, pragma Export creates a label symbol on the first byte allocated in read/write memory for the object. This symbol is the External_Name specified in the pragma (or generated by default). An Exported Ada object with External_Name L whose Ada type corresponds to C type T, may be accessed through the C declaration "extern T L;".

Warning: The External_Name specified or used by default must be unique throughout the entire program library. If there are two interface routines with the same symbol in the program library, the ld command will resolve references to this symbol to whichever it encounters first. If the compilation unit in which the pragma Export appears is not part of the program, a PROGRAM_ERROR will be raised. Thus it is recommended that you always specify a External_Name explicitly, since otherwise, the same name would be generated for the identically-named subprogram or object exported from different packages. In general, you should not expect the usual Ada semantics when mixing Ada with other languages. For example, you should not depend on constraint checks being performed on actual parameters in a call to an Ada subprogram from a non-Ada subprogram. You should not depend on constraint checks being performed on non-Ada assignments to Exported objects. If your non-Ada subprogram calls an Ada subprogram before the Ada subprogram is elaborated, the effect is not defined. An Ada subprogram called from a non-Ada subprogram must not propagate an exception out of the called subprogram. Therefore, it is recommended that you have an exception handler in your subprogram that catches all possible exceptions.

An Ada subprogram can be called directly by name or indirectly by address. To call by address, you pass the 'ADDRESS of the Ada subprogram to a non-Ada subprogram. The 'ADDRESS attribute returns the address of a function descriptor of the Ada subprogram. To call by name, you simply call the External_Name specified in pragma Export.

The parameters that you can pass to an Ada subprogram from a non-Ada subprogram are the same as the parameters you can pass to an imported subprogram. = See "Mapping Ada Data Types to Other Languages".

Example

Here is an (otherwise useless) example of how pragma Export can be used to provide access to Ada objects from a C function:

--Beginning of Ada part of example
package pkg is
  ---------------
  x : integer       :=   0; pragma export(c,x,"adax");
  y : character     := 'a'; pragma export(c,y,"aday");
  ---------------
  procedure proc;
  ---------------
end;
package body pkg is
  ---------------
  z : short_integer :=   4; pragma export(c,z,"adaz");
  ---------------
  procedure proc is
  begin -- proc
    x := integer(z);
  end proc;
  ---------------
end pkg;
  with pkg;
  with text_io;
  ---------------
procedure ada_main is
  ---------------
  procedure c;              pragma import(c,c);
  ---------------
begin
  text_io.put     (integer'image(pkg.x));
  text_io.put     (              pkg.y);
  pkg.proc; -- retrieve value of hidden z
  text_io.put_line(integer'image(pkg.x));
  c;
  text_io.put     (integer'image(pkg.x));
  text_io.put     (              pkg.y);
  pkg.proc; -- retrieve value of hidden z
  text_io.put_line(integer'image(pkg.x));
end ada_main;
--End of Ada part of example
/* Beginning of C part of example */
extern int   adax;
extern char  aday;
extern short adaz;
void c()
{
   adax =   1;
   aday = 'b';
   adaz =   5;
}
/* End of C part of example */

This is the result of compiling and linking the above Ada and C code:

 0a 4
 1b 5