Справочник Ada (Ada 2022)
B.3 Взаимодействие с C и C++
Средства, относящиеся к взаимодействию с языком C и соответствующим подмножеством языка C++, — это пакет Interfaces.C и его дочерние пакеты, а также поддержка указания атрибута Convention с convention_идентификаторами C, C_Pass_By_Copy и любыми из описанных ниже конвенций C_Variadic_n.
Пакет Interfaces.C содержит основные типы, константы и подпрограммы, которые позволяют программе Ada передавать скаляры и строки в функции C и C++. Когда в данном подпункте упоминается сущность C, это также относится к соответствующей сущности в C++.
Статическая семантика
Пакет библиотеки Interfaces.C имеет следующее объявление:
package Interfaces.C
with Pure is
with Pure is
-- Объявления, основанные на <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_bool is new Boolean;
type C_bool is new Boolean;
-- Числа с плавающей точкой
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
with Pack;
for char_array'Component_Size use CHAR_BIT;
with Pack;
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
with Pack;
with Pack;
Этот абзац был удален.
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.
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
with Pack;
with Pack;
Этот абзац был удален.
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
with Pack;
with Pack;
Этот абзац был удален.
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_bool, C_float и long_double соответственно соответствуют типам C signed char, unsigned short, unsigned long, unsigned char, bool, 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 в противном случае.
END_OF_DOCUMENT_MARKER
функция To_C (Item : входной String; Append_Nul : входной Boolean := True)
возвращает char_array;
функция To_Ada (Item : входной char_array; Trim_Nul : входной Boolean := True)
возвращает String;
возвращает char_array;
функция To_Ada (Item : входной char_array; Trim_Nul : входной Boolean := True)
возвращает String;
Результат To_C — это значение char_array длиной Item'Length (если Append_Nul — False) или Item'Length+1 (если Append_Nul — True). Нижний индекс — 0. Для каждого компонента Item(I), соответствующий компонент в результате — To_C, применённый к Item(I). Значение nul добавляется, если Append_Nul — True. Если Append_Nul — False и Item'Length — 0, To_C генерирует Constraint_Error.
Результат To_Ada — это String длиной Item'Length (если Trim_Nul — False) или длиной слайса Item до первого nul (если Trim_Nul — True). Нижний индекс результата — 1. Если Trim_Nul — False, для каждого компонента Item(I) соответствующий компонент результата — To_Ada, применённый к Item(I). Если Trim_Nul — True, то для каждого компонента Item(I) перед первым nul соответствующий компонент результата — To_Ada, применённый к Item(I). Функция генерирует Terminator_Error, если Trim_Nul — True и Item не содержит nul.
процедура To_C (Item : входной String;
Target : выходной char_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char_array;
Target : выходной String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Target : выходной char_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char_array;
Target : выходной String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Для процедуры To_C каждый элемент Item преобразуется (через функцию To_C) в char, который присваивается соответствующему элементу Target. Если Append_Nul — True, затем nul присваивается следующему элементу Target. В любом случае Count устанавливается в число присвоенных элементов Target. Если Target недостаточно велик, генерируется Constraint_Error.
Для процедуры To_Ada каждый элемент Item (если Trim_Nul — False) или каждый элемент Item перед первым nul (если Trim_Nul — True) преобразуется (через функцию To_Ada) в Character, который присваивается соответствующему элементу Target. Count устанавливается в число присвоенных элементов Target. Если Target недостаточно велик, генерируется Constraint_Error. Если Trim_Nul — True и Item не содержит nul, генерируется Terminator_Error.
функция Is_Nul_Terminated (Item : входной wchar_array) возвращает Boolean;
Результат Is_Nul_Terminated — True, если Item содержит wide_nul, и False в противном случае.
функция To_C (Item : входной Wide_Character) возвращает wchar_t;
функция To_Ada (Item : входной wchar_t ) возвращает Wide_Character;
функция To_Ada (Item : входной wchar_t ) возвращает Wide_Character;
To_C и To_Ada предоставляют отображение между Ada и C широкими типами символов.
функция To_C (Item : входной Wide_String;
Append_Nul : входной Boolean := True)
возвращает wchar_array;
функция To_Ada (Item : входной wchar_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_String;
процедура To_C (Item : входной Wide_String;
Target : выходной wchar_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной wchar_array;
Target : выходной Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Append_Nul : входной Boolean := True)
возвращает wchar_array;
функция To_Ada (Item : входной wchar_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_String;
процедура To_C (Item : входной Wide_String;
Target : выходной wchar_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной wchar_array;
Target : выходной Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Подпрограммы To_C и To_Ada, преобразующие между Wide_String и wchar_array, имеют аналогичное действие подпрограммам To_C и To_Ada, преобразующим между String и char_array, за исключением того, что используется wide_nul вместо nul.
функция Is_Nul_Terminated (Item : входной char16_array) возвращает Boolean;
Результат Is_Nul_Terminated — True, если Item содержит char16_nul, и False в противном случае.
функция To_C (Item : входной Wide_Character) возвращает char16_t;
функция To_Ada (Item : входной char16_t ) возвращает Wide_Character;
функция To_Ada (Item : входной char16_t ) возвращает Wide_Character;
To_C и To_Ada предоставляют отображение между Ada и C 16-битными типами символов.
функция To_C (Item : входной Wide_String;
Append_Nul : входной Boolean := True)
возвращает char16_array;
функция To_Ada (Item : входной char16_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_String;
процедура To_C (Item : входной Wide_String;
Target : выходной char16_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char16_array;
Target : выходной Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Append_Nul : входной Boolean := True)
возвращает char16_array;
функция To_Ada (Item : входной char16_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_String;
процедура To_C (Item : входной Wide_String;
Target : выходной char16_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char16_array;
Target : выходной Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Подпрограммы To_C и To_Ada, преобразующие между Wide_String и char16_array, имеют аналогичное действие подпрограммам To_C и To_Ada, преобразующим между String и char_array, за исключением того, что используется char16_nul вместо nul.
функция Is_Nul_Terminated (Item : входной char32_array) возвращает Boolean;
Результат Is_Nul_Terminated — True, если Item содержит char32_nul, и False в противном случае.
функция To_C (Item : входной Wide_Wide_Character) возвращает char32_t;
функция To_Ada (Item : входной char32_t ) возвращает Wide_Wide_Character;
функция To_Ada (Item : входной char32_t ) возвращает Wide_Wide_Character;
To_C и To_Ada предоставляют отображение между Ada и C 32-битными типами символов.
функция To_C (Item : входной Wide_Wide_String;
Append_Nul : входной Boolean := True)
возвращает char32_array;
функция To_Ada (Item : входной char32_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_Wide_String;
процедура To_C (Item : входной Wide_Wide_String;
Target : выходной char32_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char32_array;
Target : выходной Wide_Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Append_Nul : входной Boolean := True)
возвращает char32_array;
функция To_Ada (Item : входной char32_array;
Trim_Nul : входной Boolean := True)
возвращает Wide_Wide_String;
процедура To_C (Item : входной Wide_Wide_String;
Target : выходной char32_array;
Count : выходной size_t;
Append_Nul : входной Boolean := True);
процедура To_Ada (Item : входной char32_array;
Target : выходной Wide_Wide_String;
Count : выходной Natural;
Trim_Nul : входной Boolean := True);
Подпрограммы To_C и To_Ada, преобразующие между Wide_Wide_String и char32_array, имеют аналогичное действие подпрограммам To_C и To_Ada, преобразующим между String и char_array, за исключением того, что используется char32_nul вместо nul.
Аспект Convention с идентификатором_convention_идентификатор C_Pass_By_Copy должен быть задан только для типа.
Правила применимости в B.1 не применяются к конвенции C_Pass_By_Copy. Вместо этого тип T подходит для конвенции C_Pass_By_Copy, если T — это тип неконтролируемого объединения или если T — это тип записи без дискриминантов и у которого все компоненты имеют статически ограниченные подтипы, и каждый компонент совместим с C.
Если тип совместим с C_Pass_By_Copy, то он также совместим с C.
Идентификаторы C_Variadic_0, C_Variadic_1, C_Variadic_2 и т. д. являются идентификаторами_convention_идентификатор. Эти конвенции называются C_Variadic. Конвенция C_Variadic_n — это конвенция вызова для вариативной C-функции, принимающей n фиксированных параметров, а затем переменное количество дополнительных параметров. Конвенция C_Variadic_n должна быть задана только как аспект конвенции для подпрограммы или для типа доступа к подпрограмме, имеющей не менее n параметров. Тип совместим с конвенцией C_Variadic тогда и только тогда, когда тип совместим с C.
Требования к реализации
Реализация должна поддерживать указание аспекта Convention с C идентификатором_convention_ для C-совместимого типа (см. B.1). Реализация должна поддерживать указание аспекта Convention с C_Pass_By_Copy идентификатором_convention_ для типа, совместимого с C_Pass_By_Copy.
Разрешения для реализации
Реализация может предоставить дополнительные объявления в пакетах C-интерфейса.
Реализация не обязана поддерживать указание аспекта Convention с идентификатором_convention_ C в следующих случаях:
- для подпрограммы, имеющей параметр неограниченного массива подтипа, если для подпрограммы аспект Import не имеет значения True;
- для функции с неограниченным массивом результата подтипа;
- для объекта, номинальный подтип которого — неограниченный массив подтипа.
Рекомендации для реализации
Постоянные nul, wide_nul, char16_nul и char32_nul должны иметь представление ноль.
Реализация должна поддерживать следующие соответствия интерфейсов между Ada и C.
- Ada процедура соответствует C-функции, возвращающей void.
- Ada функция соответствует C-функции, не возвращающей void.
- Тип Ada перечисления соответствует типу C перечисления с соответствующими литералами перечисления, имеющими те же внутренние коды, при условии, что внутренние коды попадают в диапазон типа C int.
- Ada входной скалярный параметр передаётся как скалярный аргумент в C-функцию.
- Ada входной параметр типа доступа к объекту с заданным типом T передаётся как t* аргумент в C-функцию, где t — тип C, соответствующий типу Ada T.
- Ada параметр access T или Ada выходной или входно-выходной параметр элементарного типа T передаётся как t* аргумент в C-функцию, где t — тип C, соответствующий типу Ada T. В случае элементарного выходного или входно-выходного параметра используется указатель на временную копию для сохранения семантики по копированию.
- Ada параметр типа (записи) T с конвенцией C_Pass_By_Copy, с режимом входной, передаётся как t аргумент в C-функцию, где t — C структура, соответствующая типу Ada T.
- Ada параметр типа записи T, отличный от входного параметра типа с конвенцией C_Pass_By_Copy, передаётся как t* аргумент в C-функцию, с модификатором const, если режим Ada — входной, где t — C структура, соответствующая типу Ada T.
- Параметр Ada типа массива с компонентами типа T передается в функцию C как аргумент t*, с модификатором const, если режим Ada — in, где t — тип C, соответствующий типу Ada T.
- Параметр Ada типа доступа к подпрограмме передается как указатель на функцию C, прототип которой соответствует спецификации указанной подпрограммы.
- Параметр Ada приватного типа передается, как указано для полного представления типа.
- Правила соответствия, указанные выше для параметров режима in, также применяются к возвращаемому объекту функции.
Реализация должна предоставить unsigned_long_long и long_long как 64-битные целочисленные типы с модулем и знаком (соответственно) в пакете Interfaces.C, если реализация C поддерживает unsigned long long и long long как 64-битные типы.
ПРИМЕЧАНИЕ 1 Значения типа char_array не неявно завершаются нулём. Если char_array должен передаваться как параметр в импортированную функцию C, требующую завершения нулём, ответственность за получение этого эффекта лежит на программисте.
ПРИМЕЧАНИЕ 2 Чтобы получить эффект C's sizeof(item_type), где Item_Type — соответствующий тип Ada, оцените выражение: size_t(Item_Type'Size/CHAR_BIT).
Этот абзац был удален.
ПРИМЕЧАНИЕ 3 Функция C с переменным числом аргументов может соответствовать нескольким подпрограммам Ada, принимающим различное количество и типы параметров.
Примеры
Пример использования пакета Interfaces.C:
--Вызов функций библиотеки C strcpy и printf
with Interfaces.C;
procedure Test is
package C renames Interfaces.C;
use type C.char_array;
-- Вызов <string.h>strcpy:
-- C определение strcpy: char *strcpy(char *s1, const char *s2);
-- Эта функция копирует строку, на которую указывает s2 (включая завершающий нулевой символ)
-- в массив, на который указывает s1. Если копирование происходит между перекрывающимися объектами,
-- поведение не определено. Функция strcpy возвращает значение s1.
with Interfaces.C;
procedure Test is
package C renames Interfaces.C;
use type C.char_array;
-- Вызов <string.h>strcpy:
-- C определение strcpy: char *strcpy(char *s1, const char *s2);
-- Эта функция копирует строку, на которую указывает s2 (включая завершающий нулевой символ)
-- в массив, на который указывает s1. Если копирование происходит между перекрывающимися объектами,
-- поведение не определено. Функция strcpy возвращает значение s1.
-- Примечание: так как возвращаемое значение функции C не интересует, интерфейс Ada является процедурой
procedure Strcpy (Target : out C.char_array;
Source : in C.char_array)
with Import => True, Convention => C, External_Name => "strcpy";
procedure Strcpy (Target : out C.char_array;
Source : in C.char_array)
with Import => True, Convention => C, External_Name => "strcpy";
-- Вызов <sdtio.h>printf:
-- C определение printf: int printf ( const char * format, ... );
-- Эта функция записывает строку C, на которую указывает format, в стандартный вывод (stdout).
-- Если format включает спецификаторы формата (подпоследовательности, начинающиеся с %), дополнительные
-- аргументы, следующие за format, форматируются и вставляются в результирующую строку
-- заменяя соответствующие спецификаторы. Если количество аргументов не соответствует
-- количеству спецификаторов формата, или если типы аргументов не соответствуют
-- соответствующему спецификатору формата, поведение не определено. При успехе, функция
-- printf возвращает общее количество записанных символов в стандартный вывод.
-- Если произошла ошибка записи, возвращается отрицательное число.
-- C определение printf: int printf ( const char * format, ... );
-- Эта функция записывает строку C, на которую указывает format, в стандартный вывод (stdout).
-- Если format включает спецификаторы формата (подпоследовательности, начинающиеся с %), дополнительные
-- аргументы, следующие за format, форматируются и вставляются в результирующую строку
-- заменяя соответствующие спецификаторы. Если количество аргументов не соответствует
-- количеству спецификаторов формата, или если типы аргументов не соответствуют
-- соответствующему спецификатору формата, поведение не определено. При успехе, функция
-- printf возвращает общее количество записанных символов в стандартный вывод.
-- Если произошла ошибка записи, возвращается отрицательное число.
-- Примечание: так как возвращаемое значение функции C не интересует, интерфейс Ada является процедурой
procedure Printf (Format : in C.char_array;
Param1 : in C.char_array;
Param2 : in C.int)
with Import => True, Convention => C_Variadic_1, External_Name => "printf";
procedure Printf (Format : in C.char_array;
Param1 : in C.char_array;
Param2 : in C.int)
with Import => True, Convention => C_Variadic_1, External_Name => "printf";
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
Printf("The String=%s, Length=%d", Chars1, Chars1'Length);
end Test;