[Python-Dev] Re: example of module interface to a varargs function?

Skip Montanaro skip@pobox.com (Skip Montanaro)
Tue, 19 Jun 2001 17:01:13 -0500


    >> The only place in the standard modules I saw that processed a truly
    >> arbitrary number of arguments is the struct_pack method of the struct
    >> module, and it doesn't use PyArg_Parse* to process them.  Can someone
    >> point me to an example of marshalling arbitrary numbers of arguments
    >> then calling a varargs function?

    Martin> In a true varargs function, you cannot use PyArg_Parse*.
    Martin> Instead, you have to iterate over the argument tuple with
    Martin> PyTuple_GetItem, fetching one argument after another.

I think it would be nice if PyArg_ParseTuple and friends took a "*" format
character.  It would only be useful at the end of a format string, but would
allow the generic argument parsing machinery to be used for those arguments
that precede it.  The argument it writes into would be an int, which would
represent the offset of the first argument not processed by
PyArg_ParseTuple.  Reusing my example:

    void
    gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
				  guint           keyval,
				  guint           modifiers,
				  const gchar    *signal_name,
				  guint           n_args,
				  ...)

If I had a Python module wrapper function for this it might call
PyArg_ParseTuple as

    PyArg_ParseTuple(args, "iis*", &keyval, &modifiers, &signal_name, &offset);

Processing of the rest of the argument list would be the responsibility of
the author and start at args[offset].

    >> (I'll worry about calling gtk_binding_entry_add_signal after I figure
    >> out how to marshal the args.)

    Martin> I'd worry about this first: In C, it is not possible to call a
    Martin> true varargs function in a portable way if the caller doesn't
    Martin> statically (i.e. in source code) know the number of
    Martin> arguments. Only the callee can be variable, not the caller.

Understood.  It turns out that the function I used as an example is actually
only called in a few distinct ways.  I can analyze its var-arguments fairly
easily and dispatch to the appropriate call to the underlying function.

    Martin> However, I'd rather recommend to look for alternatives to
    Martin> gtk_binding_entry_add_signal. E.g. gtk_binding_entry_add_signall
    Martin> accepts a GSList*, which is a chained list of arguments, instead
    Martin> of being varargs. This you can call in a C module - the other
    Martin> one is out of reach.

Hmm... thanks, this does look like the correct solution.  I failed to notice
the distinction between the two functions when I first scanned the source
code, the signall (two-els) version is never called outside of
gtkbindings.c, the Gtk documentation in this area is, well, rather sparse,
to say the least (nine comments over 1200 lines of code, the only two
substatial ones of which are boilerplate at the top), and there is no
reference manual documentation for any of the interesting functions.  By
comparison, the Python documentation looks as if Guido has employed a team
of full-time tech writers for years.  Way to go, Fred!

Skip