你如何从 Ada 调用 scanf ?也就是说,大概有一个适当的 pragma import 声明,但声明会是什么样子?
(我对如何从 Ada 调用更不守规矩的 C 函数感兴趣,而不是如何解析字符串本身,所以我不是在寻找纯 Ada 解决方案。我的设置是 Gnat、Ubuntu Linux、x64 如果它有所作为。)
你如何从 Ada 调用 scanf ?也就是说,大概有一个适当的 pragma import 声明,但声明会是什么样子?
(我对如何从 Ada 调用更不守规矩的 C 函数感兴趣,而不是如何解析字符串本身,所以我不是在寻找纯 Ada 解决方案。我的设置是 Gnat、Ubuntu Linux、x64 如果它有所作为。)
这篇论文指出
Ada 无法声明一个函数,该函数采用不同数量的不同类型的参数。可以声明一组“printf”函数,它们接受一个字符串、一个字符串和一个整数、一个字符串和一个浮点数、一个字符串和 2 个整数,等等,然后将每个函数声明为 Import (C) 2. 但这需要大量声明,针对应用程序中的每种不同用途声明,因此它确实不实用。
也是如此scanf()
,Ada 2012 具有额外的好处,可以让您在out
和access
参数规范之间进行选择(在早期版本中,您必须使用access
,因为函数不允许有out
参数)。
此外,我不认为 C 编译器必须对可变参数函数使用与普通函数相同的参数传递机制(参考提示,我记得但现在找不到最近的对话在这些线上)。
也就是说,这里有一个在 GCC 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
格式参数中的 !)
一种解决方法是在 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);
}
然后用 . 在 Ada 中声明重载的 scan() 函数pragma Import
。
这样,您就不会尝试从 Ada 调用可变参数函数;所有固定到可变的转换都发生在 C 端。只要所有包装器都正确编写,与直接调用scanf()
.
对于要传递的每组参数类型,您只需要一个不同的包装器。
如果您只有几个电话,这可能没问题,但它不能很好地扩展。