Annotated Ada Reference ManualLegal Information
Contents   Index   References   Search   Previous   Next 

B.3 Interfacing with C and C++

1/2
{8652/0059} {AI95-00131-01} {AI95-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
{AI95-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's <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/0060} {AI95-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/0060} {AI95-00037-01}    type wchar_t is <implementation-defined character type>;
31/1
{8652/0060} {AI95-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
{AI95-00285-01}    -- ISO/IEC 10646:2003 compatible types defined by ISO/IEC TR 19769:2004.
39.2/2
{AI95-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
{AI95-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
{AI95-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/0114} {AI95-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
{AI95-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
{AI95-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
{AI95-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
{AI95-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
{AI95-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
{AI95-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
{AI95-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/0059} {AI95-00131-01} A Convention pragma with convention_identifier C_Pass_By_Copy shall only be applied to a type.
60.14/2
   {8652/0059} {AI95-00131-01} {AI95-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/0059} {AI95-00131-01} If a type is C_Pass_By_Copy-compatible then it is also C-compatible.

Implementation Requirements

61/1
{8652/0059} {AI95-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/0060} {AI95-00037-01} {AI95-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
An Ada procedure corresponds to a void-returning C function. 
64.a
Discussion: The programmer can also choose an Ada procedure when the C function returns an int that is to be discarded.
65
An Ada function corresponds to a non-void C function.
66
An Ada in scalar parameter is passed as a scalar argument to a C function.
67
An Ada in parameter of an access-to-object type with designated type T is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T.
68
An Ada access T parameter, or an Ada out or in out parameter of an elementary type T, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. In the case of an elementary out or in out parameter, a pointer to a temporary copy is used to preserve by-copy semantics.
68.1/2
{8652/0059} {AI95-00131-01} {AI95-00343-01} An Ada parameter of a (record) type T of convention C_Pass_By_Copy, of mode in, is passed as a t argument to a C function, where t is the C struct corresponding to the Ada type T.
69/2
{8652/0059} {AI95-00131-01} {AI95-00343-01} An Ada parameter of a record type T, of any mode, other than an in parameter of a type of convention C_Pass_By_Copy, is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T.
70
An Ada parameter of an array type with component type T, of any mode, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T.
71
An Ada parameter of an access-to-subprogram type is passed as a pointer to a C function whose prototype corresponds to the designated subprogram's specification. 
71.1/2
  {AI95-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
8  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
9  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.{AI95-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 C Library Function strcpy
with Interfaces.C;
procedure Test is
   package C renames Interfaces.C;
   use type C.char_array;
   -- Call <string.h>strcpy:
   -- C 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 C function's return value is of no interest, the Ada interface is a 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
{AI95-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/0059} {AI95-00131-01} {extensions to Ada 95} Corrigendum: Convention C_Pass_By_Copy is new. 

Wording Changes from Ada 95

84.c/2
{8652/0060} {AI95-00037-01} Corrigendum: Clarified the intent for Nul and Wide_Nul.
84.d/2
{AI95-00216-01} Specified that an unchecked union type (see B.3.3) is eligible for convention C_Pass_By_Copy.
84.e/2
{AI95-00258-01} Specified what happens if the To_C function tries to return a null string.
84.f/2
{AI95-00337-01} Clarified that the interface correspondences also apply to private types whose full types have the specified characteristics.
84.g/2
{AI95-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
{AI95-00376-01} Added wording to make it clear that these facilities can also be used with C++. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Sponsored by Ada-Europe