从 Ada 调用 scanf

发布于 2024-12-25 16:12:24 字数 179 浏览 2 评论 0原文

如何从 Ada 调用 scanf ?也就是说,大概有一个适当的 pragma import 声明,但是声明会是什么样子呢?

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

How do you call scanf from Ada? That is, presumably with an appropriate pragma import declaration, but what would the declaration look like?

(I'm interested in how to call C functions of the more unruly variety from Ada, not how to parse strings per se, so I'm not looking for a pure Ada solution. My setup is Gnat, Ubuntu Linux, x64 if it makes a difference.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清音悠歌 2025-01-01 16:12:24

本文要点出那个

Ada 无法声明采用不同数量、不同类型的参数的函数。可以声明一组“printf”函数,这些函数接受一个字符串、一个字符串和一个整数、一个字符串和一个浮点数、一个字符串和 2 个整数等等,然后将每个函数声明为 Import (C) 2.但这需要大量的声明,一个声明用于应用程序中的每种不同类型的用途,所以这确实不切实际。

scanf() 也是如此,它在 Ada 2012 中具有额外的好处,可以让您在 outaccess 参数规格之间进行选择(在早期版本中,您必须使用 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!)

This paper points out that

Ada has no way of declaring a function that takes different numbers of parameters of different types. One could declare a set of “printf” functions which take a string, a string and an integer, a string and a floating point number, a string and 2 integers, and so on, and then declare each one to be Import (C)2. But this requires lots of declarations, one for each different kind of use in the application program, so it really isn’t practical.

The same would be true of scanf(), which with Ada 2012 has the added bonus of letting you choose between out and access parameter specs (in earlier revisions, you had to use access because functions weren’t allowed to have out parameters).

In addition, I don’t believe it’s required that the C compiler has to use the same parameter passing mechanisms for variadic functions as it does for ordinary ones (the reference hints at this, and I recall but can’t now find a recent conversation on these lines).

That said, here’s an example which appears to work fine on Mac OS X with GCC 4.6.0:

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;

(not sure about the \n in the format parameter!)

羁绊已千年 2025-01-01 16:12:24

一种解决方法是在 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 调用可变参数函数;而是尝试从 Ada 调用可变参数函数。所有固定到可变的转换都发生在 C 端。只要所有包装器都正确编写,您就可以获得比直接调用 scanf() 更多的类型检查。

您只需要为您想要传递的每组参数类型提供一个不同的包装器。

如果您只有几个调用,这可能没问题,但它的扩展性不好。

One workaround would be to declare multiple non-variadic wrapper functions in C, and import them in Ada.

For example:

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);
}

and then declare overloaded scan() function in Ada with pragma Import.

This way, you're not attempting to call variadic functions from Ada; all the fixed-to-variadic conversion happens on the C side. And as long as all the wrappers are written correctly, you get more type checking than you would with a direct call to scanf().

You just need a distinct wrapper for each set of parmaeter types you want to pass.

This is probably ok if you only have a few calls, but it doesn't scale well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文