从Ada程序启动可执行文件并读取结果

从Ada程序启动可执行文件并读取结果,ada,gnat,Ada,Gnat,我发现了这个问题,第一个答案包含一些示例代码,演示了如何使用Ada代码启动可执行文件。可执行文件的输出被写入标准输出 我必须读取可执行文件的输出,以便在Ada中进行进一步的解析/处理(例如逐行) 如果您使用GNAT,那么您可能需要查看GNAT.Expect包中的Get\u Command\u Output。下面是一个例子: with Ada.Text_IO, GNAT.Expect; procedure Main is Command : constant String := "

我发现了这个问题,第一个答案包含一些示例代码,演示了如何使用Ada代码启动可执行文件。可执行文件的输出被写入标准输出


我必须读取可执行文件的输出,以便在Ada中进行进一步的解析/处理(例如逐行)

如果您使用GNAT,那么您可能需要查看
GNAT.Expect
包中的
Get\u Command\u Output
。下面是一个例子:

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.
可以看出,结果以单个字符串的形式返回。你得自己把线分开


更新

以下是对一些评论的回应

你也可以考虑使用这个函数,如果你的目标是Windows平台(也请参阅POST)。引用函数引用:

系统函数将命令传递给命令解释器,解释器将字符串作为操作系统命令执行

这与程序
cmd.exe
的功能类似。您可以通过将命令的输出重定向到文件(即使用
)并随后将其读回来获取命令的输出。下面是一个例子:

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;
带有Ada.Text\u IO;
使用Ada.Text\u IO.Unbounded\u IO;
使用Ada.Strings.Unbounded;
具有接口;
使用接口C.string;
主要程序是
使用Ada.Strings.Unbounded;
内容:无界\u字符串:=Null\u无界\u字符串;
开始
--执行。
声明
使用接口;
使用Interfaces.C.string;
功能系统(命令:chars_ptr)返回int
对于导入,约定=>C,外部名称=>“系统”;
命令:chars_ptr:=New_字符串(“gnat--version>gnat_version.out”);
结果:int:=系统(命令);
开始
--检查结果值(本例中省略)。
自由(指挥);
结束;
--阅读。
声明
使用Ada.Text\u IO;
使用Ada.Text\u IO.Unbounded\u IO;
Fd:文件类型;
开始
打开(Fd,In_文件,“./gnat_version.out”);
而不是结束\u文件(Fd)循环的\u
内容:=内容
&无界_字符串(获取_行(Fd))
&ASCII.CR&ASCII.LF;——恢复Get_line删除的换行符。
端环;
关闭(fd);
结束;
--表演。
Ada.Text\u IO.Unbounded\u IO.Put(内容);
端干管;

一个选项是使用管道,正如在这个问题中所解释的:您的代码示例工作正常,但我注意到一个奇怪的行为(在Windows 7上):如果一个任务循环运行,您的代码示例和另一个任务使用
Ada.Text\u IO.Put\u Line写入标准输出
,通常情况下,变量
Output
包含的不是已执行程序的预期输出,而是第二个任务写入标准输出的最后一行或多行。我遗漏了什么吗?我怀疑GNAT.Expect.Get\u命令\u输出不是线程安全的。特别是,当
Get_命令输出
与引擎盖下的标准流(
stdin
stdout
stderr
)交互时(参见示例),我将避免同时执行
Get_命令输出
和任何其他标准流相关子程序(例如,
Put_Line
stdout
)为了防止竞争条件或其他类型的意外行为。好的,我无法避免同时执行。我正在使用基于类型
GNAT.Semaphores.Binary_Semaphores
的互斥锁,以防止不同任务同时执行多个命令。我尝试了过程
Spawn
并读取文件内容使用方法将t转换为字符串。不幸的是,结果是相同的。如何使用输出重定向在系统级执行命令?例如:
ls>/path/to/output file.txt
。根据我在
Spawn
函数附近的注释中读到的内容(请参阅),从任务派生新进程通常是有问题的,应该避免。这些注释还提供了一个可能的解决方案(请参阅)。我用一个小示例扩展了我的答案,说明了如何在系统级别(仅限Windows)执行命令,但我不能保证从任务中执行命令时它会起作用。