你如何从Ada拨打scanf?也就是说,大概有一个适当的pragma导入声明,但声明会是什么样的?
(我对如何调用Ada更难以控制的C函数感兴趣,而不是如何解析字符串本身,所以我不是在寻找纯粹的Ada解决方案。我的设置是Gnat,Ubuntu Linux, x64如果有所作为。)
答案 0 :(得分:2)
Ada无法声明一个不同类型参数的函数。可以声明一组“printf”函数,它们接受一个字符串,一个字符串和一个整数,一个字符串和一个浮点数,一个字符串和2个整数,依此类推,然后将每个函数声明为Import(C) 2。但这需要大量的声明,一个用于应用程序中每种不同类型的使用,所以它实际上是不实际的。
对于scanf()
也是如此,Ada 2012还有额外的好处,让您可以在out
和access
参数规格之间进行选择(在之前的版本中,您必须使用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()
更多的类型检查。
您只需要为要传递的每组parmaeter类型设置一个独特的包装器。
如果你只有几个电话,这可能没问题,但它不能很好地扩展。