TOC PREV NEXT INDEX DOC LIST MASTER INDEX



Interfacing with Other Languages

In Ada, a subprogram written in another language can be called from an Ada program (Ada83 LRM 13.10.2, Ada95 LRM 13.9).

The LRM does not provide for calling Ada routines from other languages; this can be done with Rational Ada.

When writing a program that contains source code in both Ada and another language, you must follow certain restrictions and methodologies. This chapter discusses:

If you are using Apex Duo, additional information on including C/C++ code in an Ada program can be found in the Programmer's Guide.


General Information 

When writing a multilanguage program (one that contains code written in other languages as well as Ada) using Apex, you cannot:

When writing a multilanguage program (one that contains code written in other languages as well as Ada) using Apex, you can:


Program Structure

This section discusses the following topics:

Non-Ada Subsystems

In general, place non-Ada code into a separate subsystem from the Ada code that interfaces with it. This provides a logical separation of code with different requirements.

Structuring the Main Program

Elaboration code is not generated automatically in a multilanguage program for non-Ada units. The code to elaborate all the compilation units in the closure of a program is generated only for a main Ada procedure.


Warning: Because of this, the main entry point for any mixed-language program must be in Ada.

Construct your program as follows:

1 . Create a set of Ada packages to contain the declarations for all non-Ada routines to be called from the main program.

For example:

2 . Create an Ada procedure to serve as the main entry point for the program.

In this Ada main program, with the Ada closure of any non-Ada routines (that is, any Ada called from the non-Ada routine), include the packages created in step 1 . For example:

You might have several layers similar to this. For example, another Ada package Ada_X that is linked with the main Ada procedure would with an associated Ada_X_C_Specs package containing the interface declarations for C routines used in Ada_X.

3 . Code the Ada main program and any other Ada units in its closure as you normally would.

4 . Link the Ada main program as described in Linking.

These last two steps can be combined.

Code Restrictions


Warning: Your program must observe the following restrictions.

Interfacing Pragmas

For the import or export of non-Ada procedures, functions, and variables, Apex Ada supports the following pragmas the following Interfacing pragmas (AARM B.1) for both Ada83 and Ada95:

pragma Import

This pragma allows an entity from a foreign language to be imported by an Ada program, so that a foreign-language subprogram can be called or a foreign-language object accessed from Ada.

The syntax is

where...

Required Parameters

Convention -- Apex Ada allows one the following calling conventions:

Entity – The identifier Ada uses for the object or subprogram imported from the foreign language.

Optional Parameters

External_Name The entity's identifier in the foreign code. The default is the entity_ID. For C, the default is the entity_ID converted to lower case.

For example, the identifier "sqrt" of this C function

If upper and lower case letters appear in the identifier in foreign code where case is significant (C or Asm), you must supply the external name explicitly.

In the following example, Ada imports the abs function from the standard C math library but must change the name (to Absolute_Value, in the example) because abs is a reserved word in Ada.

C:

Ada:

The syntax of the pragma in this example shows parameters passed by position. If they were passed by name, the syntax would be:

Link_Name – The link name in the external code of the entity to be imported. By default, the compiler generates the link name from the external name using the convention of the compiler for the foreign language. In the example above, on a Sun platform, the compiler would construct a link name using Solaris conventions: "_abs"

Importing Objects

The examples given above are of entities that are subprograms. Here is an example of applying pragma Import to an entity which is an object, C's errno variable. Ada imports it to be a part of a package of UNIX interface entities:

C side –

Ada side –

pragma Export

This pragma allows Ada subprograms to be called and Ada objects accessed by foreign-language programs.

The syntax is

where...

Required Parameters pragma Export

pragma Export uses the same required parameters as pragma Import.

Convention – Can be C, Ada, or Asm. C is the version of the C or C++ language that was used to compile the operating system of the current platform.

Entity – The local (Ada) name of the object or subprogram to be exported to the foreign language.

Optional Parameters for pragma Export

External_Name -- The foreign code identifier of the entity being exported from Ada. The default is the Ada entity_ID in lower-case. If a different identifier, including one using upper-case letters is required in the foreign code, it must be entered explicitly.

Example of exporting a function from Ada to C:

Ada:

C:

Exporting Objects

As with pragma Inline, the examples given above are of subprograms; pragma Export handles objects similarly to pragma Import.

Ada:

C:

pragma Convention

This pragma is used for specifying that an Ada subprogram or type should use the conventions of another language. It is useful for defining subprograms for callback operations.

The syntax is:

where:

For example, it is frequently convenient to call a C routine that has a callback as a parameter:

In Ada, the routine that has the callback parameter must have its calling convention specified as C:

When a convention of C is specified for a record type, the layout of the record is C-compatible (i.e., the same layout as would be generated by the C compiler for a corresponding C struct). In particular, the compiler does not reorder fields in this case. See "Record Types" in the Ada Runtime Guide for more information.

pragma Calling_Convention

Pragma Calling_Convention is always used in conjunction with pragma Import or pragma Export. Additional information on, and Apex specific extensions to, pragma Calling_Convention can be found in implementation dependent Pragma Calling_Convention (also available in Pragma Calling_Convention).

Pragmas Import and Export tell the compiler that a certain subprogram is imported from or exported to another language. Pragma Calling_Convention gives additional instructions to the compiler about specific calling conventions to be used. This affects the code generated by the compiler for the subprogram call (if imported) or for the subprogram prologue and epilog (when exported). The syntax is:

Pragma Calling_Convention can be used to enable the running of different IEEE floating point models within the same program. For example, a project's C/C++ code uses the extended IEEE programming mathematics "model". That is, instead of exceptions occurring on overflows, underflows, or erroneous computations (such as divide by zero or square root of a negative number), the C/C++ code expects IEEE NaN and Inf values to be produced, with the intent that somewhere within C/C++ there will be a test for these values with appropriate actions at that point.

The existing Ada code depends on a finite-values-only IEEE model, in which any of the above occurrences cause an exception to be raised.

There is a fundamental incompatibility between the two models. Code can be written for either model in either language, but once written, running the code with the opposite model leads to faulty execution. What is needed is a way to run both models within the same program, switching back and forth as appropriate.

The Apex compiler has support for exactly this situation, but does require the application code to make it clear when the model is to be changed. Specifically, any calls out to C/C++ and any callbacks into Ada from C/C++ must use the appropriate pragma to indicate that the FP control state is to be changed.

For C/C++ procedures that are "imported" via a pragma Import, there must be a pragma Calling_Convention with Floating_Point_Control_Preserve set to True (the name of the pragma feature is an anachronistic misnomer; the effect is backwards from what you might expect from the name). For Ada procedures that are called from C/C++ the same calling convention must be applied. For example:

Applied to an Import, this causes the "calling code" to save the FP control state, change it to the value of the symbol __FP_CONTROL_FOR_C, call the routine, and upon return from the routine, restore the FP control state.

Applied to an Export, this generates subroutine preamble code to save the FP control state and change it to the value of the symbol __FP_CONTROL_FOR_ADA. It also generates subroutine post-amble code that restores the FP control state on exit from the subroutine.

The value of __FP_CONTROL_FOR_C is initialized during startup from the C_FLOATING_POINT_CONTROL field in the user's configuration table (in file v_usr_conf.2.ada).

The value for __FP_CONTROL_FOR_ADA is initialized during startup from the FLOATING_POINT_CONTROL in the user's configuration table (in file v_usr_conf.2.ada). Currently, this item must be identical to the same item in the kernel configuration table (in file v_krn_conf.2.ada).


Warning: The values in FP data registers are NOT affected by this pragma or the generated code. Only the FP control status register, which controls what to do when abnormal values are generated, is affected.

Parameter Passing

Ada and Assembly Language

When mixing Ada code and assembly-language routines, you need to specify a language convention of Asm for the Export pragmas.

When specifying the external name for an imported assembler program or an Ada subprogram exported to an assembler program, match the name that you give to your assembler routine.

When providing this name, avoid the following naming prefixes:


Compiling the C Code

To compile the C (or C++) routines that will be linked with the Ada main program, use the cc command with the following arguments:


Linking


Warning: For all platforms except SunOS and AIX, external archives and object files linked with Apex Ada must not define the symbol "main". For SunOS, external archives must not define "_main". For AIX, external archives must not define ".main".

To link an Ada main program named Ada_Main that includes non-Ada routines:

1 . Set the NON_ADA_LINKAGE context switch (or use the corresponding command-line option) in the view from which you will link your Ada main program.

Its value is a string that contains linker arguments. At a minimum, specify:

    Note: cc automatically includes libc.a and modules to do C-library initialization. If the Profiling switch or command option is used, profiling support libraries are also included.

pragma Linker_Options

Passes arguments to the target linker. The syntax is:

Usage

This pragma can appear in any package specification or declarative part. Its argument is passed as a command line argument to the target linker whenever the unit containing the pragma is in the closure of the main program being linked.

In constructing the target linker command line argument, the Link_With argument is first divided into tokens. Tokens are delimited by white-space.

Tokens are then passed to the linker command line. Tokens beginning with "+" and "-" tokens are interpreted as linker switches. Tokens beginning with "/" tokens are interpreted as rooted filenames. If a token begins with "-", "+", or "/", it is left untouched.

If a token begins with neither "-" nor "+" nor "/", then it is assumed to name a file and is prefixed with pathname of the directory containing the Ada unit in which the pragma appears. (This behavior is different from VADS, in which unqualified names are interpreted in the context of the main program being linked).

If a main program's closure contains more than one pragma Linker_Options, their contents will be separated by blanks on the linker command line. The order in which the arguments appear is not defined.

If pragma Linker_Options appears in the implementation of an API, that is, in a unit that also contains pragma Api, its contents are passed to the linker when the API is used in the closure of a main program, not when the API itself is linked.

Note that pragma Linker_Options is feature-identical with, and replaces, the obsolete pragma Link_With.


Rational Software Corporation 
http://www.rational.com
support@rational.com
techpubs@rational.com
Copyright © 1993-2004, Rational Software Corporation. All rights reserved.
TOC PREV NEXT INDEX DOC LIST MASTER INDEX TECHNOTES APEX TIPS