在Ada中如何调用外部程序?
如何从Ada程序文本中调用外部命令(就像我在unixshell或Windows命令提示符下键入命令一样) 我更喜欢非特定于蚊虫的解决方案,但无论如何,我会将我自己的发现作为初始答案发布。在Ada中如何调用外部程序?,ada,gnat,Ada,Gnat,如何从Ada程序文本中调用外部命令(就像我在unixshell或Windows命令提示符下键入命令一样) 我更喜欢非特定于蚊虫的解决方案,但无论如何,我会将我自己的发现作为初始答案发布。with gnat.OS_Lib; 主要程序是 退出代码:整数; 开始 退出代码:=GNAT.OS_Lib.Spawn(程序名=>“mv”,参数=>(新字符串'(“README.md”),新字符串'(“README.txt”); 如果退出_Code/=0,则 使用“退出代码”引发程序错误:&退出代码图像; 如果结
with gnat.OS_Lib;
主要程序是
退出代码:整数;
开始
退出代码:=GNAT.OS_Lib.Spawn(程序名=>“mv”,参数=>(新字符串'(“README.md”),新字符串'(“README.txt”);
如果退出_Code/=0,则
使用“退出代码”引发程序错误:&退出代码图像;
如果结束;
端干管;
如果您在windows上,请将“mv”更改为“move”
有关非阻塞和/或捕获stdout/stderr的信息,请参阅扩展此功能。您也可以使用
系统。支持于,例如
- Linux()
- 窗口()
请注意,错误会写入标准错误
main.adb
with Ada.Text_IO;
with Interfaces.C;
procedure Main is
package C renames Interfaces.C;
use type C.int;
function system (command : C.char_array) return C.int
with Import, Convention => C;
command : aliased constant C.char_array :=
C.To_C ("mv README.md README.txt");
result : C.int;
begin
result := system (command);
if result = 0 then
Ada.Text_IO.Put_Line ("OK");
else
Ada.Text_IO.Put_Line ("Failed");
end if;
end Main;
with Ada.Text_IO; use Ada.Text_IO;
with POSIX; use POSIX;
with POSIX.Process_Primitives;
with POSIX.Process_Identification;
procedure Main is
package PP renames POSIX.Process_Primitives;
package PI renames POSIX.Process_Identification;
Filename : constant POSIX_String := "sleep";
Args : POSIX_String_List;
PID : PI.Process_ID;
PT : PP.Process_Template;
PS : PP.Termination_Status;
begin
Append (Args, Filename); -- argv[0]
Append (Args, "5"); -- argv[1]
PP.Open_Template (PT);
PP.Start_Process_Search
(Child => PID,
Filename => Filename,
Template => PT,
Arg_List => Args);
loop
Put_Line ("Waiting...");
PP.Wait_For_Child_Process
(Status => PS,
Child => PID,
Block => False);
exit when PP.Status_Available (PS);
delay 1.0;
end loop;
Put_Line ("The child terminated with status code: "
& PP.Exit_Status_Of (PS)'Image);
PP.Close_Template (PT);
end Main;
基于我对花店图书馆的评论(参见),我添加了另一个例子(仅供参考和参考,而不是作为对原始问题的严肃回答)。不幸的是,我在评论中提到的Florist版本没有根据GNAT的最新版本(例如GNAT CE 2020)进行编译。这个版本的库似乎在某种程度上依赖于GNAT的内部结构,而GNAT的内部结构经过了轻微的修改(因此库不再像最初预期的那样独立于编译器)。尽管如此,为了完整性,如果您能够编译它(使用较旧版本的GNAT或修复源代码),那么下面的示例将在不阻塞的情况下生成一个子进程,并等待它完成
main.adb
with Ada.Text_IO;
with Interfaces.C;
procedure Main is
package C renames Interfaces.C;
use type C.int;
function system (command : C.char_array) return C.int
with Import, Convention => C;
command : aliased constant C.char_array :=
C.To_C ("mv README.md README.txt");
result : C.int;
begin
result := system (command);
if result = 0 then
Ada.Text_IO.Put_Line ("OK");
else
Ada.Text_IO.Put_Line ("Failed");
end if;
end Main;
with Ada.Text_IO; use Ada.Text_IO;
with POSIX; use POSIX;
with POSIX.Process_Primitives;
with POSIX.Process_Identification;
procedure Main is
package PP renames POSIX.Process_Primitives;
package PI renames POSIX.Process_Identification;
Filename : constant POSIX_String := "sleep";
Args : POSIX_String_List;
PID : PI.Process_ID;
PT : PP.Process_Template;
PS : PP.Termination_Status;
begin
Append (Args, Filename); -- argv[0]
Append (Args, "5"); -- argv[1]
PP.Open_Template (PT);
PP.Start_Process_Search
(Child => PID,
Filename => Filename,
Template => PT,
Arg_List => Args);
loop
Put_Line ("Waiting...");
PP.Wait_For_Child_Process
(Status => PS,
Child => PID,
Block => False);
exit when PP.Status_Available (PS);
delay 1.0;
end loop;
Put_Line ("The child terminated with status code: "
& PP.Exit_Status_Of (PS)'Image);
PP.Close_Template (PT);
end Main;
输出
$./obj/main
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
Waiting...
The child terminated with status code: 0
我们有一个很好的带有异步通知的流程API。看一看。它可以在Linux、Windows和Mac OS X上工作。可以选择与Glib事件循环集成
Args : Spawn.String_Vectors.UTF_8_String_Vector;
L : aliased Listeners.Listener;
begin
Args.Append ("Hello World");
P.Set_Program ("/bin/echo");
P.Set_Arguments (Args);
P.Set_Working_Directory ("/tmp");
P.Set_Listener (L'Unchecked_Access);
P.Start;
对于非阻塞系统调用,您将如何执行此操作?我惊讶地发现GNAT.OS_Lib.Spawn没有在引擎盖下调用系统。它称为“u_gnat_portable_spawn”,非阻塞的_spawn也会这样做;同样,这是因为我正在寻找一些东西来取代GNAT运行时特定的“\uuu GNAT\u portable\u no\u block\u spawn”,这样代码将使用任何Ada编译器进行编译。@TamaMcGlinn如果您不想在OS_Lib
中使用GNAT特定的抽象,那么恐怕您将不得不使用OS特定的C系统调用,最有可能的是使用的那些会产生(参见示例)。Ada本身(即标准库)不知道进程的概念。@TamaMcGlinn对于与POSIX兼容的操作系统的交互(例如启动进程等),在某个时间点,有一个POSIX Ada语言接口可用(请参阅和Wiki页)以及一个名为(有关流程原语,请参见posix-process\u primitives.ads
)。但是,这个库似乎有些不推荐使用。