Ада-95. Компилятор GNAT



         

Примеры организации взаимодействия с C - часть 2


---------------------------------------------------------- type String_Ptr is access all String; type String_Array is array(Natural range <>) of String_Ptr;

function execv( Path : String; Arg_List : String_Array) return Interfaces.C.Int;

--------------------------------------------------------- -- execv заменяет текущий процесс на новый. -- Список аргументов передается как параметры командной -- строки для вызываемой программы. -- -- Для вызова этой подпрограммы можно: -- -- Option2 : aliased String := "-b"; -- Option3 : aliased String := "-c"; -- Option4 : String := "Cxy"; -- Result : Interfaces.C.Int; -- ... -- Result := execv(Path => "some_program", -- -- построение массива указателей на строки... -- argv => String_Array'(new String'("some_program"), -- new String'("-a"), -- Option2'Unchecked_Access, -- Option3'Unchecked_Access, -- new String'('-' & Option4)); -- -- Допустимо использовать любую комбинацию -- динамически размещаемых строк и 'Unchecked_Access -- к aliased переменным. -- Однако, необходимо отметить, что нельзя выполнить -- "some_String"'Access, поскольку Ада требует имя, -- а не значение, для отрибута 'Access

------------------------------------------------------------

Теперь, реализация может быть выполнена следующим образом:

function execv( Path : String; argv : String_Array ) return Interfaces.C.Int is

Package C renames Interfaces.C; Package Strings renames Interfaces.C.Strings;

C_Path : constant Strings.Chars_Ptr(1..Path'Length + 1) := Strings.New_String(Path);

type Char_Star_Array is array(1..argv'Length + 1) of

Strings.Char_Array_Ptr;

C_Argv : Char_Star_Array; Index : Integer; Result : C.int;

------------------------------------------------------------ function C_Execv( Path : Strings.Char_Ptr; C_Arg_List : Strings.Char_Ptr) return C.int; pragma Import(C, C_Execv, "execv"); ------------------------------------------------------------

begin

-- установка массива указателей на строки

Index := 0; for I in argv'Range loop

Index := Index + 1; C_Argv(Index) := Strings.New_String(argv(I).all)); end loop;

-- добавление C-значения null в конец массива адресов

C_Argv(C_Argv'Last) := Strings.Null_Ptr;

-- передача адресов первых элементов каждого параметра, -- как это ожидает C

Result := C_Execv( C_Path(1)'Address, C_Argv(1)'Address));

-- освобождение памяти, поскольку часто это не выполняется

for I in argv'Range loop

Strings.Free(argv(I)); end loop;

Strings.Free(C_Path);

return Result; end execv;

Примечательно, что передается адрес первого элемента массива, а не адрес самого массива.

Массивы, описываемые как неограниченные, зачастую содержат вектор с дополнительной информацией, которая включает верхнюю и нижнюю границу массива.

Copyright (C) А.Гавва V-0.4w май 2004




Содержание  Назад  Вперед