Запустите исполняемый файл из программы на Аде и прочитайте результат

Я нашел вопрос это, и первый ответ содержит пример кода, демонстрирующий, как запустить исполняемый файл с кодом Ада. Вывод исполняемого файла записывается в стандартный вывод.

Какие параметры у меня есть для чтения вывода исполняемого файла для дальнейшего анализа/обработки в Аде (например, построчно)?

Один из вариантов - использовать канал, как объясняется в этом вопросе: stackoverflow.com/questions/48187514/…

NeoSer 15.06.2019 12:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
672
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы используете GNAT, возможно, вам стоит взглянуть на Get_Command_Output в пакете GNAT.Expect. Вот пример:

with Ada.Text_IO, GNAT.Expect;

procedure Main is

   Command    : constant String := "gnat";   
   Argument_1 : aliased String  := "--version";
   Input      : constant String := ""; 
   Status     : aliased Integer := 0;      

   --  Execute the command and retrieve the output.

   Output : String :=
              GNAT.Expect.Get_Command_Output
                (Command    => Command,
                 Arguments  => (1 => Argument_1'Unchecked_Access),
                 Input      => Input,
                 Status     => Status'Access,
                 Err_To_Out => False);

   --  NOTE: Cheating with Unchecked_Access, OK for demo. You may want
   --        to properly new and Free these strings (see Argument_List 
   --        type in package GNAT.OS_Lib).

begin  
   Ada.Text_IO.Put_Line (Output);
end Main;

Программа возвращается после выполнения:

$ ./main
GNAT Community 2019 (20190517-83)
Copyright (C) 1996-2019, Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Как видно, результат возвращается в виде одной строки. Вам придется сделать разделение линии самостоятельно.


Обновлять

Обновление в ответ на некоторые комментарии ниже.

Вы также можете рассмотреть возможность использования функции system, если вы ориентируетесь на платформу Windows (см. также пост это на SO). Цитата из ссылки на функцию:

The system function passes command to the command interpreter, which executes the string as an operating-system command.

Это похоже на то, что делает программа cmd.exe. Вы можете получить вывод команды, перенаправив ее вывод в файл (т. е. используя >), а затем прочитать его обратно. Вот пример:

with Ada.Text_IO;              
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings.Unbounded;

with Interfaces.C;
with Interfaces.C.Strings;         

procedure Main is

   use Ada.Strings.Unbounded;
   Content : Unbounded_String := Null_Unbounded_String;   

begin

   --  Execute.
   declare   

      use Interfaces.C;
      use Interfaces.C.Strings; 

      function system (command : chars_ptr) return int
        with Import, Convention => C, External_Name => "system";      

      command : chars_ptr := New_String("gnat --version > gnat_version.out");
      result  : int       := system (command); 

   begin
      --  Check value of result (omitted in this example).
      Free(Command);
   end;

   --  Read.
   declare

      use Ada.Text_IO;
      use Ada.Text_IO.Unbounded_IO;  

      Fd : File_Type;

   begin  
      Open (Fd, In_File, "./gnat_version.out");
      while not End_Of_File (Fd) loop
         Content := Content 
           & Unbounded_String'(Get_Line (Fd))
           & ASCII.CR & ASCII.LF;   --  Restore the line break removed by Get_Line.
      end loop;
      Close (fd);
   end;

   --  Show.
   Ada.Text_IO.Unbounded_IO.Put (Content);   

end Main;

Ваш пример кода работает нормально, но я заметил странное поведение (в Windows 7): если одна задача циклически выполняет ваш пример кода, а другая задача записывает в стандартный вывод, используя Ada.Text_IO.Put_Line, часто бывает, что переменная Output содержит не ожидаемый результат выполняемая программа, но последняя или несколько строк, которые были записаны второй задачей в стандартный вывод. Я что-то пропустил?

Marcello90 12.07.2019 19:36

Я подозреваю, что GNAT.Expect.Get_Command_Output не является потокобезопасным. В частности, поскольку Get_Command_Output взаимодействует со стандартными потоками (stdin, stdout и stderr) под капотом (см., например, здесь), я бы избегал одновременного выполнения Get_Command_Output и любых других подпрограмм, связанных со стандартными потоками (например, от Put_Line до stdout), чтобы предотвратить условия гонки или другие виды неожиданного поведения.

DeeDee 13.07.2019 12:11

Хорошо, я не могу избежать одновременного исполнения. Я использую мьютекс на основе типа GNAT.Semaphores.Binary_Semaphore, чтобы предотвратить одновременное выполнение нескольких команд из разных задач. Я попробовал процедуру этоSpawn и прочитал содержимое файла в строку, используя метод это. К сожалению, результат тот же. Как я могу выполнить команду на системном уровне, используя перенаправление вывода? Например: ls > /path/to/output-file.txt.

Marcello90 13.07.2019 19:35

Из того, что я прочитал в комментариях рядом с функцией Spawn (см. здесь), создание нового процесса из задачи в целом проблематично, и его следует избегать. Комментарии также предоставляют возможное решение (см. здесь). Я расширил свой ответ небольшим примером того, как вы можете выполнить команду на системном уровне (только для Windows), но я не могу гарантировать, что она будет работать, когда она выполняется из задачи.

DeeDee 14.07.2019 12:33

Другие вопросы по теме