Next: , Previous: B.2, Up: Annex B


B.3 Interfacing with C and C++

1/2
{8652/00598652/0059} {00131AI95−00131−01} {00376AI95−00376−01} {interface to C} {C interface} The facilities relevant to interfacing with the C language and the corresponding subset of the C++ language are the package Interfaces.C and its children; support for the Import, Export, and Convention pragmas with convention_identifier C; and support for the Convention pragma with convention_identifier C_Pass_By_Copy.

2/2
{00376AI95−00376−01} The package Interfaces.C contains the basic types, constants and subprograms that allow an Ada program to pass scalars and strings to C and C++ functions. When this clause mentions a C entity, the reference also applies to the corresponding entity in C++.

Static Semantics

3
The library package Interfaces.C has the following declaration:

4

     package Interfaces.C is   pragma Pure(C);

5

        −− Declarations based on C'<limits.h>

6

        CHAR_BIT  constant := implementation−defined;  −− typically 8
        SCHAR_MIN constant := implementation−defined;  −− typically −−128
        SCHAR_MAX constant := implementation−defined;  −− typically 127
        UCHAR_MAX constant := implementation−defined;  −− typically 255

7

        −− Signed and Unsigned Integers
        type int   is range implementation−defined;
        type short is range implementation−defined;
        type long  is range implementation−defined;

8

        type signed_char is range SCHAR_MIN .. SCHAR_MAX;
        for signed_char'Size use CHAR_BIT;

9

        type unsigned       is mod implementation−defined;
        type unsigned_short is mod implementation−defined;
        type unsigned_long  is mod implementation−defined;

10

        type unsigned_char is mod (UCHAR_MAX+1);
        for unsigned_char'Size use CHAR_BIT;

11

        subtype plain_char is implementation−defined;

12

        type ptrdiff_t is range implementation−defined;

13

        type size_t is mod implementation−defined;

14

        −− Floating Point

15

        type C_float     is digits implementation−defined;

16

        type double      is digits implementation−defined;

17

        type long_double is digits implementation−defined;

18

        −− Characters and Strings 

19

        type char is <implementation−defined character type>;

20/1

     {8652/00608652/0060} {00037AI95−00037−01}    nul constant char := implementation−defined;

21

        function To_C   (Item in Character) return char;

22

        function To_Ada (Item in char) return Character;

23

        type char_array is array (size_t range <>) of aliased char;
        pragma Pack(char_array);
        for char_array'Component_Size use CHAR_BIT;

24

        function Is_Nul_Terminated (Item in char_array) return Boolean;

25

        function To_C   (Item       in String;
                         Append_Nul in Boolean := True)
           return char_array;

26

        function To_Ada (Item     in char_array;
                         Trim_Nul in Boolean := True)
           return String;

27

        procedure To_C (Item       in  String;
                        Target     out char_array;
                        Count      out size_t;
                        Append_Nul in  Boolean := True);

28

        procedure To_Ada (Item     in  char_array;
                          Target   out String;
                          Count    out Natural;
                          Trim_Nul in  Boolean := True);

29

        −− Wide Character and Wide String

30/1

     {8652/00608652/0060} {00037AI95−00037−01}    type wchar_t is <implementation−defined character type>;

31/1

     {8652/00608652/0060} {00037AI95−00037−01}    wide_nul constant wchar_t := implementation−defined;

32

        function To_C   (Item in Wide_Character) return wchar_t;
        function To_Ada (Item in wchar_t       return Wide_Character;

33

        type wchar_array is array (size_t range <>) of aliased wchar_t;

34

        pragma Pack(wchar_array);

35

        function Is_Nul_Terminated (Item in wchar_array) return Boolean;

36

        function To_C   (Item       in Wide_String;
                         Append_Nul in Boolean := True)
           return wchar_array;

37

        function To_Ada (Item     in wchar_array;
                         Trim_Nul in Boolean := True)
           return Wide_String;

38

        procedure To_C (Item       in  Wide_String;
                        Target     out wchar_array;
                        Count      out size_t;
                        Append_Nul in  Boolean := True);

39

        procedure To_Ada (Item     in  wchar_array;
                          Target   out Wide_String;
                          Count    out Natural;
                          Trim_Nul in  Boolean := True);

39.1/2

     {00285AI95−00285−01}    −− ISO/IEC 10646:2003 compatible types defined by ISO/IEC TR 19769:2004.

39.2/2

     {00285AI95−00285−01}    type char16_t is <implementation−defined character type>;

39.3/2

        char16_nul constant char16_t := implementation−defined;

39.4/2

        function To_C (Item in Wide_Character) return char16_t;
        function To_Ada (Item in char16_t) return Wide_Character;

39.5/2

        type char16_array is array (size_t range <>) of aliased char16_t;

39.6/2

        pragma Pack(char16_array);

39.7/2

        function Is_Nul_Terminated (Item in char16_array) return Boolean;
        function To_C (Item       in Wide_String;
                       Append_Nul in Boolean := True)
           return char16_array;

39.8/2

        function To_Ada (Item     in char16_array;
                         Trim_Nul in Boolean := True)
           return Wide_String;

39.9/2

        procedure To_C (Item       in  Wide_String;
                        Target     out char16_array;
                        Count      out size_t;
                        Append_Nul in  Boolean := True);

39.10/2

        procedure To_Ada (Item     in  char16_array;
                          Target   out Wide_String;
                          Count    out Natural;
                          Trim_Nul in  Boolean := True);

39.11/2

     {00285AI95−00285−01}    type char32_t is <implementation−defined character type>;

39.12/2

        char32_nul constant char32_t := implementation−defined;

39.13/2

        function To_C (Item in Wide_Wide_Character) return char32_t;
        function To_Ada (Item in char32_t) return Wide_Wide_Character;

39.14/2

        type char32_array is array (size_t range <>) of aliased char32_t;

39.15/2

        pragma Pack(char32_array);

39.16/2

        function Is_Nul_Terminated (Item in char32_array) return Boolean;
        function To_C (Item       in Wide_Wide_String;
                       Append_Nul in Boolean := True)
           return char32_array;

39.17/2

        function To_Ada (Item     in char32_array;
                         Trim_Nul in Boolean := True)
           return Wide_Wide_String;

39.18/2

        procedure To_C (Item       in  Wide_Wide_String;
                        Target     out char32_array;
                        Count      out size_t;
                        Append_Nul in  Boolean := True);

39.19/2

        procedure To_Ada (Item     in  char32_array;
                          Target   out Wide_Wide_String;
                          Count    out Natural;
                          Trim_Nul in  Boolean := True);

40

        Terminator_Error exception;

41

     end Interfaces.C;

41.a.1/2

Implementation defined: The definitions of certain types and constants in Interfaces.C.

42
Each of the types declared in Interfaces.C is C−compatible.

43/2
{00285AI95−00285−01} The types int, short, long, unsigned, ptrdiff_t, size_t, double, char, wchar_t, char16_t, and char32_t correspond respectively to the C types having the same names. The types signed_char, unsigned_short, unsigned_long, unsigned_char, C_float, and long_double correspond respectively to the C types signed char, unsigned short, unsigned long, unsigned char, float, and long double.

43.a/2

Discussion: The C types wchar_t and char16_t seem to be the same. However, wchar_t has an implementation−defined size, whereas char16_t is guaranteed to be an unsigned type of at least 16 bits. Also, char16_t and char32_t are encouraged to have UTF−16 and UTF−32 representations; that means that they are not directly the same as the Ada types, which most likely don't use any UTF encoding.

44
The type of the subtype plain_char is either signed_char or unsigned_char, depending on the C implementation.

45

     function To_C   (Item in Character) return char;
     function To_Ada (Item in char     return Character;

46

The functions To_C and To_Ada map between the Ada type Character and the C type char.

46.a.1/1

Implementation Note: {8652/01148652/0114} {00038AI95−00038−01} The To_C and To_Ada functions map between corresponding characters, not necessarily between characters with the same internal representation. Corresponding characters are characters defined by the same enumeration literal, if such exist; otherwise, the correspondence is unspecified.{Unspecified [partial]}

46.a.2/1

The following definition is equivalent to the above summary:

46.a.3/1

To_C (Latin_1_Char) = char'Value(Character'Image(Latin_1_Char))
provided that char'Value does not raise an exception; otherwise the result is unspecified.

46.a.4/1

To_Ada (Native_C_Char) = Character'Value(char'Image(Native_C_Char))
provided that Character'Value does not raise an exception; otherwise the result is unspecified.

47

     function Is_Nul_Terminated (Item in char_array) return Boolean;

48

The result of Is_Nul_Terminated is True if Item contains nul, and is False otherwise.

49

     function To_C   (Item in String;     Append_Nul in Boolean := True)
        return char_array;
     
     function To_Ada (Item in char_array; Trim_Nul   in Boolean := True)
        return String;

50/2

{00258AI95−00258−01} The result of To_C is a char_array value of length Item'Length (if Append_Nul is False) or Item'Length+1 (if Append_Nul is True). The lower bound is 0. For each component Item(I), the corresponding component in the result is To_C applied to Item(I). The value nul is appended if Append_Nul is True. If Append_Nul is False and Item'Length is 0, then To_C propagates Constraint_Error.

51

The result of To_Ada is a String whose length is Item'Length (if Trim_Nul is False) or the length of the slice of Item preceding the first nul (if Trim_Nul is True). The lower bound of the result is 1. If Trim_Nul is False, then for each component Item(I) the corresponding component in the result is To_Ada applied to Item(I). If Trim_Nul is True, then for each component Item(I) before the first nul the corresponding component in the result is To_Ada applied to Item(I). The function propagates Terminator_Error if Trim_Nul is True and Item does not contain nul.

52

     procedure To_C (Item       in  String;
                     Target     out char_array;
                     Count      out size_t;
                     Append_Nul in  Boolean := True);
     
     procedure To_Ada (Item     in  char_array;
                       Target   out String;
                       Count    out Natural;
                       Trim_Nul in  Boolean := True);

53

For procedure To_C, each element of Item is converted (via the To_C function) to a char, which is assigned to the corresponding element of Target. If Append_Nul is True, nul is then assigned to the next element of Target. In either case, Count is set to the number of Target elements assigned. {Constraint_Error (raised by failure of run−time check)} If Target is not long enough, Constraint_Error is propagated.

54

For procedure To_Ada, each element of Item (if Trim_Nul is False) or each element of Item preceding the first nul (if Trim_Nul is True) is converted (via the To_Ada function) to a Character, which is assigned to the corresponding element of Target. Count is set to the number of Target elements assigned. {Constraint_Error (raised by failure of run−time check)} If Target is not long enough, Constraint_Error is propagated. If Trim_Nul is True and Item does not contain nul, then Terminator_Error is propagated.

55

     function Is_Nul_Terminated (Item in wchar_array) return Boolean;

56

The result of Is_Nul_Terminated is True if Item contains wide_nul, and is False otherwise.

57

     function To_C   (Item in Wide_Character) return wchar_t;
     function To_Ada (Item in wchar_t       return Wide_Character;

58

To_C and To_Ada provide the mappings between the Ada and C wide character types.

59

     function To_C   (Item       in Wide_String;
                      Append_Nul in Boolean := True)
        return wchar_array;
     
     function To_Ada (Item     in wchar_array;
                      Trim_Nul in Boolean := True)
        return Wide_String;
     
     procedure To_C (Item       in  Wide_String;
                     Target     out wchar_array;
                     Count      out size_t;
                     Append_Nul in  Boolean := True);
     
     procedure To_Ada (Item     in  wchar_array;
                       Target   out Wide_String;
                       Count    out Natural;
                       Trim_Nul in  Boolean := True);

60

The To_C and To_Ada subprograms that convert between Wide_String and wchar_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that wide_nul is used instead of nul.

60.1/2

     function Is_Nul_Terminated (Item in char16_array) return Boolean;

60.2/2

{00285AI95−00285−01} The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.

60.3/2

     function To_C (Item in Wide_Character) return char16_t;
     function To_Ada (Item in char16_t return Wide_Character;

60.4/2

{00285AI95−00285−01} To_C and To_Ada provide mappings between the Ada and C 16−bit character types.

60.5/2

     function To_C (Item       in Wide_String;
                    Append_Nul in Boolean := True)
        return char16_array;
     
     function To_Ada (Item     in char16_array;
                      Trim_Nul in Boolean := True)
        return Wide_String;
     
     procedure To_C (Item       in  Wide_String;
                     Target     out char16_array;
                     Count      out size_t;
                     Append_Nul in  Boolean := True);
     
     procedure To_Ada (Item     in  char16_array;
                       Target   out Wide_String;
                       Count    out Natural;
                       Trim_Nul in  Boolean := True);

60.6/2

{00285AI95−00285−01} The To_C and To_Ada subprograms that convert between Wide_String and char16_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char16_nul is used instead of nul.

60.7/2

     function Is_Nul_Terminated (Item in char32_array) return Boolean;

60.8/2

{00285AI95−00285−01} The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.

60.9/2

     function To_C (Item in Wide_Wide_Character) return char32_t;
     function To_Ada (Item in char32_t return Wide_Wide_Character;

60.10/2

{00285AI95−00285−01} To_C and To_Ada provide mappings between the Ada and C 32−bit character types.

60.11/2

     function To_C (Item       in Wide_Wide_String;
                    Append_Nul in Boolean := True)
        return char32_array;
     
     function To_Ada (Item     in char32_array;
                      Trim_Nul in Boolean := True)
        return Wide_Wide_String;
     
     procedure To_C (Item       in  Wide_Wide_String;
                     Target     out char32_array;
                     Count      out size_t;
                     Append_Nul in  Boolean := True);
     
     procedure To_Ada (Item     in  char32_array;
                       Target   out Wide_Wide_String;
                       Count    out Natural;
                       Trim_Nul in  Boolean := True);

60.12/2

{00285AI95−00285−01} The To_C and To_Ada subprograms that convert between Wide_Wide_String and char32_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char32_nul is used instead of nul.

60.a

Discussion: The Interfaces.C package provides an implementation−defined character type, char, designed to model the C run−time character set, and mappings between the types char and Character.

60.b

One application of the C interface package is to compose a C string and pass it to a C function. One way to do this is for the programmer to declare an object that will hold the C array, and then pass this array to the C function. This is realized via the type char_array:

60.c

     type char_array is array (size_t range <>) of Char;

60.d

The programmer can declare an Ada String, convert it to a char_array, and pass the char_array as actual parameter to the C function that is expecting a char *.

60.e

An alternative approach is for the programmer to obtain a C char pointer from an Ada String (or from a char_array) by invoking an allocation function. The package Interfaces.C.Strings (see below) supplies the needed facilities, including a private type chars_ptr that corresponds to C's char *, and two allocation functions. To avoid storage leakage, a Free procedure releases the storage that was allocated by one of these allocate functions.

60.f

It is typical for a C function that deals with strings to adopt the convention that the string is delimited by a nul char. The C interface packages support this convention. A constant nul of type Char is declared, and the function Value(Chars_Ptr) in Interfaces.C.Strings returns a char_array up to and including the first nul in the array that the chars_ptr points to. The Allocate_Chars function allocates an array that is nul terminated.

60.g

Some C functions that deal with strings take an explicit length as a parameter, thus allowing strings to be passed that contain nul as a data element. Other C functions take an explicit length that is an upper bound: the prefix of the string up to the char before nul, or the prefix of the given length, is used by the function, whichever is shorter. The C Interface packages support calling such functions.

60.13/1
{8652/00598652/0059} {00131AI95−00131−01} A Convention pragma with convention_identifier C_Pass_By_Copy shall only be applied to a type.

60.14/2
{8652/00598652/0059} {00131AI95−00131−01} {00216AI95−00216−01} The eligibility rules in B.1 do not apply to convention C_Pass_By_Copy. Instead, a type T is eligible for convention C_Pass_By_Copy if T is an unchecked union type or if T is a record type that has no discriminants and that only has components with statically constrained subtypes, and each component is C−compatible.

60.15/1
{8652/00598652/0059} {00131AI95−00131−01} If a type is C_Pass_By_Copy−compatible then it is also C−compatible.

Implementation Requirements

61/1
{8652/00598652/0059} {00131AI95−00131−01} An implementation shall support pragma Convention with a C convention_identifier for a C−eligible type (see B.1). An implementation shall support pragma Convention with a C_Pass_By_Copy convention_identifier for a C_Pass_By_Copy−eligible type.

Implementation Permissions

62
An implementation may provide additional declarations in the C interface packages.

Implementation Advice

62.1/2
{8652/00608652/0060} {00037AI95−00037−01} {00285AI95−00285−01} The constants nul, wide_nul, char16_nul, and char32_nul should have a representation of zero.

62.a/2

Implementation Advice: The constants nul, wide_nul, char16_nul, and char32_nul in package Interfaces.C should have a representation of zero.

63
An implementation should support the following interface correspondences between Ada and C.

64

64.a

Discussion: The programmer can also choose an Ada procedure when the C function returns an int that is to be discarded.

65

66

67

68

68.1/2

69/2

70

71

71.1/2
{00337AI95−00337−01} An Ada parameter of a private type is passed as specified for the full view of the type.

71.a/2

Implementation Advice: If C interfacing is supported, the interface correspondences between Ada and C should be supported.

     NOTES

72

 Values of type char_array are not implicitly terminated with nul. If a char_array is to be passed as a parameter to an imported C function requiring nul termination, it is the programmer's responsibility to obtain this effect.

73

 To obtain the effect of C's sizeof(item_type), where Item_Type is the corresponding Ada type, evaluate the expression: size_t(Item_Type'Size/CHAR_BIT).

74/2

This paragraph was deleted.{00216AI95−00216−01}

75

10  A C function that takes a variable number of arguments can correspond to several Ada subprograms, taking various specific numbers and types of parameters.
Examples

76
Example of using the Interfaces.C package:

77

     −−Calling the Library Function strcpy
     with Interfaces.C;
     procedure Test is
        package renames Interfaces.C;
        use type C.char_array;
        −− Call <string.h>strcpy:
        −− definition of strcpy:  char *strcpy(char *s1, const char *s2);
        −−    This function copies the string pointed to by s2 (including the terminating null character)
        −−     into the array pointed to by s1. If copying takes place between objects that overlap, 
        −−     the behavior is undefined. The strcpy function returns the value of s1.

78

        −− Note: since the function'return value is of no interest, the Ada interface is procedure
        procedure Strcpy (Target out C.char_array;
                          Source in  C.char_array);

79

        pragma Import(C, Strcpy, "strcpy");

80

        Chars1  C.char_array(1..20);
        Chars2  C.char_array(1..20);

81

     begin
        Chars2(1..6) := "qwert" C.nul;

82

        Strcpy(Chars1, Chars2);

83

     −− Now Chars1(1..6) "qwert" C.Nul

84

     end Test;
Incompatibilities With Ada 95

84.a/2

{00285AI95−00285−01} {incompatibilities with Ada 95} Types char16_t and char32_t and their related types and operations are newly added to Interfaces.C. If Interfaces.C is referenced in a use_clause, and an entity E with the same defining_identifier as a new entity in Interfaces.C is defined in a package that is also referenced in a use_clause, the entity E may no longer be use−visible, resulting in errors. This should be rare and is easily fixed if it does occur.
Extensions to Ada 95

84.b/2

{8652/00598652/0059} {00131AI95−00131−01} {extensions to Ada 95} Corrigendum: Convention C_Pass_By_Copy is new.
Wording Changes from Ada 95

84.c/2

{8652/00608652/0060} {00037AI95−00037−01} Corrigendum: Clarified the intent for Nul and Wide_Nul.

84.d/2

{00216AI95−00216−01} Specified that an unchecked union type (see B.3.3) is eligible for convention C_Pass_By_Copy.

84.e/2

{00258AI95−00258−01} Specified what happens if the To_C function tries to return a null string.

84.f/2

{00337AI95−00337−01} Clarified that the interface correspondences also apply to private types whose full types have the specified characteristics.

84.g/2

{00343AI95−00343−01} Clarified that a type must have convention C_Pass_By_Copy in order to be passed by copy (not just a type that could have that convention).

84.h/2

{00376AI95−00376−01} Added wording to make it clear that these facilities can also be used with C++.