Search code examples
scanfadagnatlanguage-interoperability

Calling scanf from Ada


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.)


Solution

  • 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!)