Can you call a C routine with a variable number of arguments from 
Author Message
 Can you call a C routine with a variable number of arguments from

I'm trying to call some C routines from Ada which have variable numbers & types
of arguments.  I was wondering if anyone has tried doing this and knows of a way
to implement an interface to a C routine which has variable numbers & types of a
rguments.


Fri, 06 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:

> I'm trying to call some C routines from Ada which have variable numbers
& types
> of arguments.  I was wondering if anyone has tried doing this and knows
of a way
> to implement an interface to a C routine which has variable numbers &
types of a
> rguments.

The trick is to declare an Ada routine for each version of the C routine
that you need to call from your Ada program.

Thus if you know that you need to pass six arguments to the routine, you
would declare the Ada routine as having six arguments and then call that
routine for that case.

There is no way to specify it in the general case...

Hope this helps,

Ken

--
Ken Anderson
Graduate Student
University of California, Irvine



Sat, 07 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from


: > I'm trying to call some C routines from Ada which have variable numbers
: & types
: > of arguments.  I was wondering if anyone has tried doing this and knows
: of a way
: > to implement an interface to a C routine which has variable numbers &
: types of a
: > rguments.

: The trick is to declare an Ada routine for each version of the C routine
: that you need to call from your Ada program.

: Thus if you know that you need to pass six arguments to the routine, you
: would declare the Ada routine as having six arguments and then call that
: routine for that case.

: There is no way to specify it in the general case...

: Hope this helps,

I have worked this out with a generic "stdarg" package.  The package
is included in an X binding I have done, and I have a paper about how
it works in the upcoming November Tri-Ada.

        Mitch Gart



Sun, 08 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:
(Kenneth M. Anderson) writes:


|>
|> > I'm trying to call some C routines from Ada which have variable numbers
|> & types
|> > of arguments.  I was wondering if anyone has tried doing this and knows
|> of a way
|> > to implement an interface to a C routine which has variable numbers &
|> types of a
|> > rguments.
|>
|> The trick is to declare an Ada routine for each version of the C routine
|> that you need to call from your Ada program.
|>
|> Thus if you know that you need to pass six arguments to the routine, you
|> would declare the Ada routine as having six arguments and then call that
|> routine for that case.
|>
|> There is no way to specify it in the general case...

An approach that is not portable, but more general for a given
implementation of C, is to determine how your implementation represents a
va_list (the standard C structure representing a variable-length
argument list) and to use Ada low-level features to construct one.
In some implementations, a pointer to this structure is passed as an
ordinary parameter, while in others it is implicit in the global state
(i.e., the arguments to be passed are simply placed into the callee's
stack frame starting at a known position, and a va_list value is just a
pointer into this list).

It would have been nice if Interfaces.C had provided a standard interface
for constructing and passing variable-length argument lists.  Then it
would be the Ada implementer's job to retarget to different C
implementations, and Ada programmers could write portable calls on C
functions with variable numbers of arguments.

One approach to constructing such an interface is to use generics:

   package Interfaces.C.Variable_Length_Argument_Lists is

      type va_list is limited private;

      procedure Make_Empty (List: va_list);

      generic
         type T (<>) is limited private;
      procedure Append (List: in out va_list; Argument: T);

   private

      [implementation dependent]

   end Interfaces.C.Variable_Length_Argument_Lists;

Example of use:

    procedure Append_Integer is new Append (Integer);
    procedure Append_Float is new Append (Float);
    Arguments: va_list;
    procedure printf (Format: in chars_ptr; Arguments: va_list);
    pragma Import (C, printf);
    N: Integer;
    ...
    Make_Empty (Arguments);
    Append_Integer (Arguments, N);
    Append_Float ( Arguments, Sqrt( Float(N) ) );
    printf (New_String("The square root of %d is %f.\n"), Arguments);

Another approach is to use streams:

   with Ada.Streams; use Ada.Streams;

   package Interfaces.C.Variable_Length_Argument_Lists is

      type va_list is new Root_Stream_Type with private;

      procedure Read
         (Stream : in out va_list;
          Item   : out Stream_Element_Array;
          Last   : out Stream_Element_Offset);
         -- Not really used, although we can think of the called C
         --    function as calling it.

      procedure Write
         (Stream : in out va_list;
          Item   : in Stream_Element_Array);
         -- Invoked through the 'Write attribute of the argument type.

   private

      [implementation dependent]

   end Interfaces.C.Variable_Length_Argument_Lists;

Example of use:

    Arguments: aliased va_list;
    procedure printf (Format: in chars_ptr; Arguments: va_list);
    pragma Import (C, printf);
    N: Integer;
    ...
    Integer'Write (Arguments'Access, N);
    Float'Write ( Arguments'Access, Sqrt( Float(N) ) );
    printf (New_String("The square root of %d is %f.\n"), Arguments);

--



Tue, 10 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

(snip)

: An approach that is not portable, but more general for a given
: implementation of C, is to determine how your implementation represents a
: va_list (the standard C structure representing a variable-length
: argument list) and to use Ada low-level features to construct one.
: In some implementations, a pointer to this structure is passed as an
: ordinary parameter, while in others it is implicit in the global state
: (i.e., the arguments to be passed are simply placed into the callee's
: stack frame starting at a known position, and a va_list value is just a
: pointer into this list).

(snip)

: One approach to constructing such an interface is to use generics:
:    package Interfaces.C.Variable_Length_Argument_Lists is
:       type va_list is limited private;
:       procedure Make_Empty (List: va_list);
:       generic
:          type T (<>) is limited private;
:       procedure Append (List: in out va_list; Argument: T);
:    private
:       [implementation dependent]
:    end Interfaces.C.Variable_Length_Argument_Lists;

(snip)

This is very close to what I have done in the Stdarg package I
wrote to go with the X Windows and Windows NT bindings I have
recently done:

    package Stdarg is

        type ArgList is private;

        -- An empty arglist, to be used in constructors:
        function Empty return ArgList;

        generic
            type T is private;
            T_Is_Modular: Boolean := False;
            T_Is_Float  : Boolean := False;
        function Concat(Args: ArgList; Arg: T) return ArgList;

    private
        ...

and then the user makes "&" functions which are instantiations
of Concat, one for each type, and then calls them with a syntax
like    

    func(Stdarg.Empty & X & Y & Z);

This spec is portable, its body is processor-dependent, but I have
ported it to 6 different chips so I'm confident that it can be
made to work on just about anything.  On the DEC alpha it was
quite challenging because the first 6 parameters are passed in
registers and the rest are passed in memory.

The implementation needed to know if a type is modular, for sign
extension, and if the type is floating point, for putting it
into the right register on the Alpha.  Thus the Boolean parameters.

Maybe it would have been a good idea to make this package a child
of Interfaces.C, I didn't think of that but it seems to fit well there.

        Mitch Gart



Fri, 13 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:
> The trick is to declare an Ada routine for each version of the C routine
> that you need to call from your Ada program.

> Thus if you know that you need to pass six arguments to the routine, you
> would declare the Ada routine as having six arguments and then call that
> routine for that case.

This will usually work, but it isn't strictly portable.  A C compiler
is free to use a different calling convention for functions taking a
variable number of arguments.

I don't know whether any existing C compilers actually do this.  It would
break any existing C code that, for example, calls printf() without a
prototype in scope.  I think C compiler vendors generally try to avoid
breaking existing code, even if it deserves to be broken.

--

TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718
Because I'm weird enough, I'm sick enough, and doggone it, people fear me!



Sat, 14 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:

>> The trick is to declare an Ada routine for each version of the C routine
>> that you need to call from your Ada program.

>This will usually work, but it isn't strictly portable.  A C compiler
>is free to use a different calling convention for functions taking a
>variable number of arguments.
>I don't know whether any existing C compilers actually do this.  It would
>break any existing C code that, for example, calls printf() without a
>prototype in scope.  I think C compiler vendors generally try to avoid
>breaking existing code, even if it deserves to be broken.

Well I recently had this problem with the C compiler for the Archimedes
under RISCOS (not the latest version BTW). Normally, this compiler passes
the first 4 arguments in registers. Called procedures may then copy as many
of these registers as they think they need onto the stack. If you use the
new ANSI-C stdarg.h and declare your called procedure with
        int scanf(char *format, ...)
then it knows to copy all 4 registers just in case. But if you declare your
procedure using the old varargs.h system (which purports to be still
supported), then it only copies 1 register, and you are stuck.

--
Charles H. Lindsey -------------------------------------------------------------


Snail: 5 Clerewood Ave., CHEADLE, SK8 3JU, U.K.   UUCP:     mucs!clerew!chl



Tue, 17 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:
> In fact I think it won't work on the Sparc.  If you call printf
> and the prototype is

>     void printf(const char *, ...);

> the first parameter will be passed in a register and the others in
> memory, laid out like in <stdarg.h>.  If you call some other function
> whose prototype is

>     void foo(const char *, int, int);

> the three parameters will all be passed in registers.

You are mistaken here.  If you were correct, it would not be possible
to call printf from C code compiled with the standard SunOS C compiler
(which does not implement prototypes).
                                Kenneth Almquist


Thu, 19 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

: : I don't know whether any existing C compilers actually do this.  It would
: : break any existing C code that, for example, calls printf() without a
: : prototype in scope.  I think C compiler vendors generally try to avoid
: : breaking existing code, even if it deserves to be broken.

: In fact I think it won't work on the Sparc.  

In fact it does work on the Sparc.  It's hard to understand how.
On the calling side parameters are put into registers, but on the
called side the va_list macros seem to be taking parameters out of
memory.



Fri, 20 Mar 1998 03:00:00 GMT  
 Can you call a C routine with a variable number of arguments from

Quote:
(Mitch Gart) writes:

|> In fact it does work on the Sparc.  It's hard to understand how.
|> On the calling side parameters are put into registers, but on the
|> called side the va_list macros seem to be taking parameters out of
|> memory.

Probably the function prologue copies registers into the newly allocated
stack frame.  xlc on AIX does this for parameters whose addresses are
taken, and use of varargs is considered equivalent to taking the address
of all parameters (or at least all those starting with the one before the
"..." in the prototype).

But I suspect we're drifting off topic ... ;-)

--



Tue, 24 Mar 1998 03:00:00 GMT  
 
 [ 11 post ] 

 Relevant Pages 

1. Eiffel cleanup #4: Routines with variable numbers of arguments

2. Question about routines with variable number of arguments

3. FORTRAN calls a C routine with variable# of arguments

4. passing functions with variable number of arguments as procedure arguments

5. Argument parsing in C module with variable number of arguments

6. porting variable argument list routines from VMS to CVF

7. Argument validity in routine calls

8. Variable number of arguments

9. Variable number of arguments to procedures

10. Syntax for variable numbers of arguments

11. define-syntax and variable numbers of arguments

12. Variable Numbers of Arguments ?

 

 
Powered by phpBB® Forum Software