Contents Index Previous Next
B.3 Interfacing with C
1/1
{
8652/0059}
{interface to C} {C
interface} The facilities relevant to interfacing
with the C language are the package Interfaces.C and its children;
and 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
The package Interfaces.C contains the basic types,
constants and subprograms that allow an Ada program to pass scalars and
strings to C functions.
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}
nul : constant char := implementation-definedchar'First;
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}
type wchar_t is <implementation-defined character type>implementation-defined;
31/1
{8652/0060}
wide_nul : constant wchar_t := implementation-definedwchar_t'First;
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);
40
Terminator_Error : exception;
41
end Interfaces.C;
41.a.1/1
Implementation defined: The
definitions of types and constants in Interfaces.C.
42
Each of the types declared in Interfaces.C is
C-compatible.
43
The types int, short, long, unsigned, ptrdiff_t,
size_t, double, char, and wchar_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.
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}
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
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.
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.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.1/1
{
8652/0059}
A Convention pragma with convention_identifier
C_Pass_By_Copy shall only be applied to a type.
60.2/1
{
8652/0059}
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 a record type that has no discriminants and that only has components
with statically constrained subtypes, and each component is C-compatible.
60.3/1
{
8652/0059}
If a type is C_Pass_By_Copy-compatible then it is also C-compatible.
Implementation Requirements
61/1
{
8652/0059}
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/1
{
8652/0060}
The constants nul and wide_nul 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/1
- {8652/0059} An
Ada parameter of a C_Pass_By_Copy-compatible (record) type T, 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/1
- {8652/0059} An Ada
parameter of a record type T, of any mode, other than an in parameter
of a C_Pass_By_Copy-compatible type, 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.
72
9 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
10 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
11 There is no explicit support
for C's union types. Unchecked conversions can be used to obtain the
effect of C unions.
75
12 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;
Contents Index Previous Next Legal