从Ada调用scanf

时间:2012-01-08 09:58:16

标签: scanf ada gnat language-interoperability

你如何从Ada拨打scanf?也就是说,大概有一个适当的pragma导入声明,但声明会是什么样的?

(我对如何调用Ada更难以控制的C函数感兴趣,而不是如何解析字符串本身,所以我不是在寻找纯粹的Ada解决方案。我的设置是Gnat,Ubuntu Linux, x64如果有所作为。)

2 个答案:

答案 0 :(得分:2)

This paper指出

  

Ada无法声明一个不同类型参数的函数。可以声明一组“printf”函数,它们接受一个字符串,一个字符串和一个整数,一个字符串和一个浮点数,一个字符串和2个整数,依此类推,然后将每个函数声明为Import(C) 2。但这需要大量的声明,一个用于应用程序中每种不同类型的使用,所以它实际上是不实际的。

对于scanf()也是如此,Ada 2012还有额外的好处,让您可以在outaccess参数规格之间进行选择(在之前的版本中,您必须使用access因为函数不允许有out个参数)。

此外,我不认为C编译器必须使用与可变参数函数相同的参数传递机制,就像普通函数一样(the reference提示,我记得但是可以'现在找到关于这些方面的最近谈话。)

那就是说,这是一个在GOS 4.6.0的Mac OS X上运行良好的例子:

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C; use Interfaces.C;
procedure Variadic is
   function Scanf (Fmt : char_array; Result : access int) return int;
   pragma Import (C, Scanf, "scanf");
   Status : int;
   Result : aliased int;
begin
   Status := Scanf (To_C ("%d\n"), Result'Access);
   Put_Line ("status: " & int'Image (Status));
   if Status = 1 then
      Put_Line ("result: " & int'Image (Result));
   end if;
end Variadic;

(不确定格式参数中的\n!)

答案 1 :(得分:2)

一种解决方法是在C中声明多个非变量包装函数,并在Ada中导入它们。

例如:

int scanf_i(const char *format, int *i_ptr) {
    return scanf(format, i_ptr);
}

int scanf_d(const char *format, double *d_ptr) {
    return scanf(format, d_ptr);
}

然后使用pragma Import在Ada中声明重载的scan()函数。

这样,你就不会试图从Ada调用可变函数;所有固定到可变的转换都发生在C端。只要所有包装器都正确写入,您就可以获得比直接调用scanf()更多的类型检查。

您只需要为要传递的每组parmae​​ter类型设置一个独特的包装器。

如果你只有几个电话,这可能没问题,但它不能很好地扩展。