PowerAda Calling Non-Ada Subprograms

From OC Systems Wiki!
Jump to: navigation, search

The PowerAda compiler supports the Ada pragma Import to enable Ada programs to call subprograms written in other languages. The compiler recognizes the Convention C for pragma Import.

The syntax of pragma Import is <RM95 B.1(5)>:

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

On AIX, the compiler converts any specified external names for C subprograms to the appropriate link name by prefixing a period to make them agree with AIX external linkage conventions. If you specify:

pragma Import(C, Program);

the compiler generates code to call the external C routine named program with the link name .program.

However, if you specify:

pragma Import(C, Program, "Program");

the compiler generates code to call the external C routine named Program with the link name .Program.

If you do not specify an External_Name or a Link_Name, you can only call non-Ada subprograms whose external names are lowercase Ada identifiers. These pragma parameters provide access to any subprogram whose name can be specified by an Ada string expression. For example, if the external name of the non-Ada subprogram you want to call begins with a leading underscore, it is not an Ada identifier and you should specify an External_Name for that subprogram.

External_Name is used to specify the linkname of an external subprogram in a portable manner. You should not prepend a dot to the External_Name string; the compiler will do this for you. Note that the string expression for External_Name is case-sensitive.

In general, you should rarely need to specify the Link_Name directly unless the subprogram being imported contains symbols or characters that are generally not legal in C subprogram names. It is more portable to specify the name as an External_Name, since different architectures use different conventions for forming a Link_Name

Stack Frame and Calling Conventions

When a non-Ada subprogram is called through pragma Import, the stack frame and calling conventions follow the AIX or Linux linkage conventions, as appropriate. The AIX calling conventions used are described in AIX Commands Reference for IBM RISC System/6000; consult that book for details.

Calling C Subprograms

You can use pragma Import to call C-language functions with the pragma:

pragma Import(C, C_Function_Name);

where C_Function_Name is a unique Ada subprogram identifier in the current scope. No Ada body may be provided for this subprogram. When the Ada name and the C name differ, the External_Name argument should be used.

Mapping Ada Parameters to C

Scalar parameters are passed by value to C while Ada composite parameters (arrays and records) are passed by reference. When you pass a record or array to a C routine, only the address of the first element is passed as a parameter. No implicit parameters, such as the array bounds, are passed to C subprograms.

Parameter modes out and in out are passed by reference to C subprograms.

There are some Ada types that cannot be passed to C and have the C subprogram access the values in anything other than as a pointer to data. For example, Ada tasks have no corresponding representation in C. Similarly, a C subprogram may expect a struct to be passed by value, but Ada cannot support such a parameter passing mode (Ada records are passed to C by reference). You may need to provide wrapper subprograms in C for Ada to call which simply translate the parameters from Ada and call the actual C subprogram. = See "Where Parameters are Passed" for information about how the compiler passes parameters to subprograms.

Finally, the package Interfaces.C provides types (and operations) that are C compatible and can be used to interface with C in a portable manner.

Calling FORTRAN, C++, and Other Subprograms

The compiler only supports the convention C, but FORTRAN, C++, and other subprograms written in non-C languages may be called from Ada using convention C.

For FORTRAN, parameters are expected to be passed by reference, so you should provide an Ada specification that uses Access parameters to pass the data. For example, to pass an integer to a routine written in FORTRAN:

procedure Call_Fortran (Num : access Integer);
pragma Import (C, Call_Fortran);

Calling C++ subprograms is done similar to calling C subprograms, except that the C++ compiler "mangles" the Link_Names (to support C++ overloading). Fortunately, C++ provides the ability to specify that a given C++ subprogram should be generated using C conventions. You do this using extern "C" for the C++ subprogram. For example, in C++:

#include <iostream.h>
extern "C" void called_from_ada(int Num)
         cout << "Called with Num = " << Num << "\n";

can be called from Ada just like any other C subprogram, using pragma Import:

procedure Called_From_Ada(Num : Integer);
pragma Import(C, Called_From_Ada);