Справочное руководство по Ada 2005
B.3 Взаимодействие с C и C++
Средства, относящиеся к взаимодействию с языком C и соответствующим подмножеством языка C++, — это пакет Interfaces.C и его дочерние элементы; поддержка директив Import, Export и Convention с convention_идентификатором C; и поддержка директивы Convention с convention_идентификатором C_Pass_By_Copy.
Пакет Interfaces.C содержит основные типы, константы и подпрограммы, которые позволяют программе Ada передавать скаляры и строки в функции C и C++. Когда в этом разделе упоминается сущность C, ссылка также относится к соответствующей сущности в C++.
Статическая семантика
Пакет-библиотека Interfaces.C имеет следующее объявление:
-- Объявления, основанные на <limits.h> в C
CHAR_BIT : constant := определяется реализацией; -- обычно 8
SCHAR_MIN : constant := определяется реализацией; -- обычно –128
SCHAR_MAX : constant := определяется реализацией; -- обычно 127
UCHAR_MAX : constant := определяется реализацией; -- обычно 255
SCHAR_MIN : constant := определяется реализацией; -- обычно –128
SCHAR_MAX : constant := определяется реализацией; -- обычно 127
UCHAR_MAX : constant := определяется реализацией; -- обычно 255
-- Целые со знаком и без знака
type int is range определяется реализацией;
type short is range определяется реализацией;
type long is range определяется реализацией;
type int is range определяется реализацией;
type short is range определяется реализацией;
type long is range определяется реализацией;
type signed_char is range SCHAR_MIN .. SCHAR_MAX;
for signed_char'Size use CHAR_BIT;
for signed_char'Size use CHAR_BIT;
type unsigned is mod определяется реализацией;
type unsigned_short is mod определяется реализацией;
type unsigned_long is mod определяется реализацией;
type unsigned_short is mod определяется реализацией;
type unsigned_long is mod определяется реализацией;
type unsigned_char is mod (UCHAR_MAX+1);
for unsigned_char'Size use CHAR_BIT;
for unsigned_char'Size use CHAR_BIT;
subtype plain_char is <тип символа, определяемый реализацией>;
type ptrdiff_t is range определяется реализацией;
type size_t is mod определяется реализацией;
-- Числа с плавающей точкой
type C_float is digits определяется реализацией;
type double is digits определяется реализацией;
type long_double is digits определяется реализацией;
-- Символы и строки
type char is <тип символа, определяемый реализацией>;
nul : constant char := определяется реализацией;
function To_C (Item : in Character) return char;
function To_Ada (Item : in char) return Character;
type char_array is array (size_t range <>) of aliased char;
pragma Pack(char_array);
for char_array'Component_Size use CHAR_BIT;
pragma Pack(char_array);
for char_array'Component_Size use CHAR_BIT;
function Is_Nul_Terminated (Item : in char_array) return Boolean;
function To_C (Item : in String;
Append_Nul : in Boolean := True)
return char_array;
Append_Nul : in Boolean := True)
return char_array;
function To_Ada (Item : in char_array;
Trim_Nul : in Boolean := True)
return String;
Trim_Nul : in Boolean := True)
return String;
procedure To_C (Item : in String;
Target : out char_array;
Count : out size_t;
Append_Nul : in Boolean := True);
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);
Target : out String;
Count : out Natural;
Trim_Nul : in Boolean := True);
-- Широкие символы и строки
type wchar_t is <тип символа, определяемый реализацией>;
wide_nul : constant wchar_t := определяется реализацией;
function To_C (Item : in Wide_Character) return wchar_t;
function To_Ada (Item : in wchar_t ) return Wide_Character;
function To_Ada (Item : in wchar_t ) return Wide_Character;
type wchar_array is array (size_t range <>) of aliased wchar_t;
pragma Pack(wchar_array);
function Is_Nul_Terminated (Item : in wchar_array) return Boolean;
function To_C (Item : in Wide_String;
Append_Nul : in Boolean := True)
return wchar_array;
Append_Nul : in Boolean := True)
return wchar_array;
function To_Ada (Item : in wchar_array;
Trim_Nul : in Boolean := True)
return Wide_String;
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);
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);
Target : out Wide_String;
Count : out Natural;
Trim_Nul : in Boolean := True);
-- Типы, совместимые с ISO/IEC 10646:2003, определенные в ISO/IEC TR 19769:2004.
type char16_t is <тип символа, определяемый реализацией>;
char16_nul : constant char16_t := определяется реализацией;
function To_C (Item : in Wide_Character) return char16_t;
function To_Ada (Item : in char16_t) return Wide_Character;
function To_Ada (Item : in char16_t) return Wide_Character;
type char16_array is array (size_t range <>) of aliased char16_t;
pragma Pack(char16_array);
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;
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;
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);
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);
Target : out Wide_String;
Count : out Natural;
Trim_Nul : in Boolean := True);
type char32_t is <тип символа, определяемый реализацией>;
char32_nul : constant char32_t := определяется реализацией;
function To_C (Item : in Wide_Wide_Character) return char32_t;
function To_Ada (Item : in char32_t) return Wide_Wide_Character;
function To_Ada (Item : in char32_t) return Wide_Wide_Character;
type char32_array is array (size_t range <>) of aliased char32_t;
pragma Pack(char32_array);
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;
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;
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);
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);
Target : out Wide_Wide_String;
Count : out Natural;
Trim_Nul : in Boolean := True);
Terminator_Error : exception;
end Interfaces.C;
Каждый из типов, объявленных в Interfaces.C, совместим с C.
Типы int, short, long, unsigned, ptrdiff_t, size_t, double, char, wchar_t, char16_t и char32_t соответственно соответствуют типам C, имеющим те же имена. Типы signed_char, unsigned_short, unsigned_long, unsigned_char, C_float и long_double соответственно соответствуют типам C signed char, unsigned short, unsigned long, unsigned char, float и long double.
Тип подтипа plain_char — это либо signed_char, либо unsigned_char, в зависимости от реализации C.
function To_C (Item : in Character) return char;
function To_Ada (Item : in char ) return Character;
function To_Ada (Item : in char ) return Character;
Функции To_C и To_Ada преобразуют между типом Ada Character и типом C char.
function Is_Nul_Terminated (Item : in char_array) return Boolean;
Результат Is_Nul_Terminated — True, если Item содержит nul, и False в противном случае.
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;
END_OF_DOCUMENT_MARKER return char_array;
function To_Ada (Item : in char_array; Trim_Nul : in Boolean := True)
return String;
Результат To_C — значение char_array длиной Item'Length (если Append_Nul ложно) или Item'Length+1 (если Append_Nul истинно). Нижняя граница — 0. Для каждого компонента Item(I) соответствующий компонент в результате — To_C, применённый к Item(I). Значение nul добавляется, если Append_Nul истинно. Если Append_Nul ложно и Item'Length равно 0, то To_C распространяет Constraint_Error.
Результат To_Ada — строка String, длина которой равна Item'Length (если Trim_Nul ложно) или длине фрагмента Item перед первым nul (если Trim_Nul истинно). Нижняя граница результата — 1. Если Trim_Nul ложно, то для каждого компонента Item(I) соответствующий компонент в результате — To_Ada, применённый к Item(I). Если Trim_Nul истинно, то для каждого компонента Item(I) перед первым nul соответствующий компонент в результате — To_Ada, применённый к Item(I). Функция распространяет Terminator_Error, если Trim_Nul истинно, а Item не содержит nul.
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);
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);
Для процедуры To_C каждый элемент Item преобразуется (через функцию To_C) в символ char, который присваивается соответствующему элементу Target. Если Append_Nul истинно, затем nul присваивается следующему элементу Target. В любом случае, Count устанавливается в число назначенных элементов Target. Если Target недостаточно длинна, распространяется Constraint_Error.
Для процедуры To_Ada каждый элемент Item (если Trim_Nul ложно) или каждый элемент Item перед первым nul (если Trim_Nul истинно) преобразуется (через функцию To_Ada) в символ Character, который присваивается соответствующему элементу Target. Count устанавливается в число назначенных элементов Target. Если Target недостаточно длинна, распространяется Constraint_Error. Если Trim_Nul истинно и Item не содержит nul, то распространяется Terminator_Error.
function Is_Nul_Terminated (Item : in wchar_array) return Boolean;
Результат Is_Nul_Terminated — True, если Item содержит wide_nul, и False в противном случае.
function To_C (Item : in Wide_Character) return wchar_t;
function To_Ada (Item : in wchar_t ) return Wide_Character;
function To_Ada (Item : in wchar_t ) return Wide_Character;
To_C и To_Ada обеспечивают сопоставление между широкими типами символов Ada и C.
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);
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);
Подпрограммы To_C и To_Ada, преобразующие Wide_String и wchar_array, имеют аналогичный эффект подпрограммам To_C и To_Ada, преобразующим String и char_array, за исключением того, что используется wide_nul вместо nul.
function Is_Nul_Terminated (Item : in char16_array) return Boolean;
Результат Is_Nul_Terminated — True, если Item содержит char16_nul, и False в противном случае.
function To_C (Item : in Wide_Character) return char16_t;
function To_Ada (Item : in char16_t ) return Wide_Character;
function To_Ada (Item : in char16_t ) return Wide_Character;
To_C и To_Ada обеспечивают сопоставление между 16-битными типами символов Ada и C.
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);
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);
Подпрограммы To_C и To_Ada, преобразующие Wide_String и char16_array, имеют аналогичный эффект подпрограммам To_C и To_Ada, преобразующим String и char_array, за исключением того, что используется char16_nul вместо nul.
function Is_Nul_Terminated (Item : in char32_array) return Boolean;
Результат Is_Nul_Terminated — True, если Item содержит char16_nul, и False в противном случае.
function To_C (Item : in Wide_Wide_Character) return char32_t;
function To_Ada (Item : in char32_t ) return Wide_Wide_Character;
function To_Ada (Item : in char32_t ) return Wide_Wide_Character;
To_C и To_Ada обеспечивают сопоставление между 32-битными типами символов Ada и C.
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);
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);
Подпрограммы To_C и To_Ada, преобразующие Wide_Wide_String и char32_array, имеют аналогичный эффект подпрограммам To_C и To_Ada, преобразующим String и char_array, за исключением того, что используется char32_nul вместо nul.
Предикат Convention с конвенцией_идентификатор C_Pass_By_Copy должен применяться только к типу.
Правила применимости в B.1 не применяются к конвенции C_Pass_By_Copy. Вместо этого тип T подходит для конвенции C_Pass_By_Copy, если T — тип объединения без проверок или если T — тип записи без дискриминаторов, у которого все компоненты имеют статически ограниченные подтипы, и каждый компонент совместим с C.
Если тип совместим с C_Pass_By_Copy, то он также совместим с C.
Требования к реализации
Реализация должна поддерживать pragma Convention с C конвенцией_идентификатор для типа, совместимого с C (см. B.1). Реализация должна поддерживать pragma Convention с C_Pass_By_Copy конвенцией_идентификатор для типа, совместимого с C_Pass_By_Copy.
Разрешения для реализации
Реализация может предоставлять дополнительные объявления в пакетах интерфейса C.
Рекомендации для реализации
Константы nul, wide_nul, char16_nul и char32_nul должны иметь представление нуля.
Реализация должна поддерживать следующие соответствия интерфейса между Ada и C.
- Процедура Ada соответствует функции C, возвращающей void.
- Функция Ada соответствует функции C, возвращающей не void.
- Скалярный параметр Ada in передаётся как скалярный аргумент функции C.
- Параметр Ada in типа доступа к объекту с назначенным типом T передаётся как t* аргумент функции C, где t — тип C, соответствующий типу Ada T.
- Параметр Ada access T или параметр Ada out или in out элементарного типа T передаётся как t* аргумент функции C, где t — тип C, соответствующий типу Ada T. В случае элементарного параметра out или in out используется указатель на временную копию для сохранения семантики по копированию.
- Параметр Ada типа (записи) T с конвенцией C_Pass_By_Copy, режима in, передаётся как t аргумент функции C, где t — структура C, соответствующая типу Ada T.
- Параметр Ada типа записи T, любого режима, кроме параметра in типа с конвенцией C_Pass_By_Copy, передаётся как t* аргумент функции C, где t — структура C, соответствующая типу Ada T.
- Параметр Ada типа массива с типом компонента T, любого режима, передаётся как t* аргумент функции C, где t — тип C, соответствующий типу Ada T.
- Параметр Ada типа доступа к подпрограмме передаётся как указатель на функцию C, прототип которой соответствует спецификации назначенной подпрограммы.
Параметр Ada приватного типа передаётся, как указано для полного представления типа.
ПРИМЕЧАНИЯ
8 Значения типа char_array не неявно завершаются nul. Если char_array должен передаваться в качестве параметра импортированной функции C, требующей завершения nul, то программист несёт ответственность за получение этого эффекта.
9 Для получения эффекта sizeof(item_type) C, где Item_Type — соответствующий тип Ada, вычислите выражение: size_t(Item_Type'Size/CHAR_BIT).
Этот абзац был удалён.
10 Функция C, принимающая переменное число аргументов, может соответствовать нескольким подпрограммам Ada, принимающим различное число и типы параметров.
Примеры
Пример использования пакета Interfaces.C:
END_OF_DOCUMENT_MARKER
--Вызов функции C Library strcpy
с Interfaces.C;
процедура Test является
пакет C переименовывает Interfaces.C;
использовать тип C.char_array;
-- Вызвать <string.h>strcpy:
-- Определение strcpy в C: char *strcpy(char *s1, const char *s2);
-- Эта функция копирует строку, на которую указывает s2 (включая завершающий нулевой символ)
-- в массив, на который указывает s1. Если копирование происходит между объектами, которые перекрываются,
-- поведение не определено. Функция strcpy возвращает значение s1.
с Interfaces.C;
процедура Test является
пакет C переименовывает Interfaces.C;
использовать тип C.char_array;
-- Вызвать <string.h>strcpy:
-- Определение strcpy в C: char *strcpy(char *s1, const char *s2);
-- Эта функция копирует строку, на которую указывает s2 (включая завершающий нулевой символ)
-- в массив, на который указывает s1. Если копирование происходит между объектами, которые перекрываются,
-- поведение не определено. Функция strcpy возвращает значение s1.
-- Примечание: так как возвращаемое значение функции C не представляет интереса, интерфейс Ada — это процедура
процедура Strcpy (Target : out C.char_array;
Source : in C.char_array);
процедура Strcpy (Target : out C.char_array;
Source : in C.char_array);
pragma Import(C, Strcpy, "strcpy");
Chars1 : C.char_array(1..20);
Chars2 : C.char_array(1..20);
Chars2 : C.char_array(1..20);
begin
Chars2(1..6) := "qwert" & C.nul;
Chars2(1..6) := "qwert" & C.nul;
Strcpy(Chars1, Chars2);
-- Теперь Chars1(1..6) = "qwert" & C.Nul
end Test;