1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <title>Variable Length Arguments</title>
5 <link rel="stylesheet" type="text/css" href="style.css">
8 <body bgcolor="#ffffff">
9 <H1><a name="Varargs"></a>13 Variable Length Arguments</H1>
11 <div class="sectiontoc">
13 <li><a href="#Varargs_nn2">Introduction</a>
14 <li><a href="#Varargs_nn3">The Problem</a>
15 <li><a href="#Varargs_nn4">Default varargs support</a>
16 <li><a href="#Varargs_nn5">Argument replacement using %varargs</a>
17 <li><a href="#Varargs_nn6">Varargs and typemaps</a>
18 <li><a href="#Varargs_nn7">Varargs wrapping with libffi</a>
19 <li><a href="#Varargs_nn8">Wrapping of va_list</a>
20 <li><a href="#Varargs_nn9">C++ Issues</a>
21 <li><a href="#Varargs_nn10">Discussion</a>
29 <b>(a.k.a, "The horror. The horror.")</b>
33 This chapter describes the problem of wrapping functions that take a
34 variable number of arguments. For instance, generating wrappers for
35 the C <tt>printf()</tt> family of functions.
39 This topic is sufficiently advanced to merit its own chapter. In
40 fact, support for varargs is an often requested feature that was first
41 added in SWIG-1.3.12. Most other wrapper generation tools have
42 wisely chosen to avoid this issue.
45 <H2><a name="Varargs_nn2"></a>13.1 Introduction</H2>
49 Some C and C++ programs may include functions that accept a variable
50 number of arguments. For example, most programmers are
51 familiar with functions from the C library such as the following:
56 int printf(const char *fmt, ...)
57 int fprintf(FILE *, const char *fmt, ...);
58 int sprintf(char *s, const char *fmt, ...);
63 Although there is probably little practical purpose in wrapping these
64 specific C library functions in a scripting language (what would be the
65 point?), a library may include its own set of special functions based
66 on a similar API. For example:
71 int traceprintf(const char *fmt, ...);
76 In this case, you may want to have some kind of access from the target language.
80 Before describing the SWIG implementation, it is important to discuss
81 the common uses of varargs that you are likely to encounter in real
82 programs. Obviously, there are the <tt>printf()</tt> style output
83 functions as shown. Closely related to this would be
84 <tt>scanf()</tt> style input functions that accept a format string and a
85 list of pointers into which return values are placed. However, variable
86 length arguments are also sometimes used to write functions that accept a
87 NULL-terminated list of pointers. A good example of this would
88 be a function like this:
93 int execlp(const char *path, const char *arg1, ...);
97 execlp("ls","ls","-l",NULL);
102 In addition, varargs is sometimes used to fake default arguments in older
103 C libraries. For instance, the low level <tt>open()</tt> system call
104 is often declared as a varargs function so that it will accept two
110 int open(const char *path, int oflag, ...);
114 f = open("foo", O_RDONLY);
115 g = open("bar", O_WRONLY | O_CREAT, 0644);
120 Finally, to implement a varargs function, recall that you have to use
121 the C library functions defined in <tt><stdarg.h></tt>. For
127 List make_list(const char *s, ...) {
134 s = va_arg(ap, const char *);
142 <H2><a name="Varargs_nn3"></a>13.2 The Problem</H2>
146 Generating wrappers for a variable length argument function presents a
147 number of special challenges. Although C provides support for
148 implementing functions that receive variable length arguments, there
149 are no functions that can go in the other direction. Specifically,
150 you can't write a function that dynamically creates a list of
151 arguments and which invokes a varargs function on your behalf.
155 Although it is possible to write functions that accept the special
156 type <tt>va_list</tt>, this is something entirely different. You
157 can't take a <tt>va_list</tt> structure and pass it in place of the
158 variable length arguments to another varargs function. It just
163 The reason this doesn't work has to do with the way that function
164 calls get compiled. For example, suppose that your program has a function call like this:
169 printf("Hello %s. Your number is %d\n", name, num);
174 When the compiler looks at this, it knows that you are calling
175 <tt>printf()</tt> with exactly three arguments. Furthermore, it knows
176 that the number of arguments as well are their types and sizes is
177 <em>never</em> going to change during program execution. Therefore,
178 this gets turned to machine code that sets up a three-argument stack
179 frame followed by a call to <tt>printf()</tt>.
183 In contrast, suppose you attempted to make some kind of wrapper around
184 <tt>printf()</tt> using code like this:
189 int wrap_printf(const char *fmt, ...) {
201 Although this code might compile, it won't do what you expect. This is
202 because the call to <tt>printf()</tt> is compiled as a procedure call
203 involving only two arguments. However, clearly a two-argument
204 configuration of the call stack is completely wrong if your intent is
205 to pass an arbitrary number of arguments to the real
206 <tt>printf()</tt>. Needless to say, it won't work.
210 Unfortunately, the situation just described is exactly the problem
211 faced by wrapper generation tools. In general, the number of passed
212 arguments will not be known until run-time. To make matters even
213 worse, you won't know the types and sizes of arguments until run-time
214 as well. Needless to say, there is no obvious way to make the C
215 compiler generate code for a function call involving an unknown number
216 of arguments of unknown types.
220 In theory, it <em>is</em> possible to write a wrapper that does the right thing.
221 However, this involves knowing the underlying ABI for the target platform and language
222 as well as writing special purpose code that manually constructed the call stack before
223 making a procedure call. Unfortunately, both of these tasks require the use of inline
224 assembly code. Clearly, that's the kind of solution you would much rather avoid.
228 With this nastiness in mind, SWIG provides a number of solutions to the varargs
229 wrapping problem. Most of these solutions are compromises that provide limited
230 varargs support without having to resort to assembly language. However, SWIG
231 can also support real varargs wrapping (with stack-frame manipulation) if you
232 are willing to get hands dirty. Keep reading.
235 <H2><a name="Varargs_nn4"></a>13.3 Default varargs support</H2>
239 When variable length arguments appear in an interface, the default
240 behavior is to drop the variable argument list entirely, replacing
241 them with a single NULL pointer. For example, if you had this
247 void traceprintf(const char *fmt, ...);
252 it would be wrapped as if it had been declared as follows:
257 void traceprintf(const char *fmt);
262 When the function is called inside the wrappers, it is called as follows:
267 traceprintf(arg1, NULL);
272 Arguably, this approach seems to defeat the whole point of variable length arguments. However,
273 this actually provides enough support for many simple kinds of varargs functions to still be useful. For
274 instance, you could make function calls like this (in Python):
277 <div class="targetlang">
279 >>> traceprintf("Hello World")
280 >>> traceprintf("Hello %s. Your number is %d\n" % (name, num))
285 Notice how string formatting is being done in Python instead of C.
288 <H2><a name="Varargs_nn5"></a>13.4 Argument replacement using %varargs</H2>
292 Instead of dropping the variable length arguments, an alternative approach is to replace
293 <tt>(...)</tt> with a set of suitable arguments. SWIG provides a special <tt>%varargs</tt> directive
294 that can be used to do this. For example,
299 %varargs(int mode = 0) open;
301 int open(const char *path, int oflags, ...);
306 is equivalent to this:
311 int open(const char *path, int oflags, int mode = 0);
316 In this case, <tt>%varargs</tt> is simply providing more specific information about the
317 extra arguments that might be passed to a function.
318 If the parameters to a varargs function are of uniform type, <tt>%varargs</tt> can also
319 accept a numerical argument count as follows:
324 %varargs(10,char *arg = NULL) execlp;
326 int execlp(const char *path, const char *arg1, ...);
331 This would wrap <tt>execlp()</tt> as a function that accepted up to 10 optional arguments.
332 Depending on the application, this may be more than enough for practical purposes.
336 Argument replacement is most appropriate in cases where the types of
337 the extra arguments is uniform and the maximum number of arguments is
338 known. When replicated argument replacement is used, at least one extra
339 argument is added to the end of the arguments when making the function call.
340 This argument serves as a sentinel to make sure the list is properly terminated.
341 It has the same value as that supplied to the <tt>%varargs</tt> directive.
345 Argument replacement is not as useful when working with functions that accept
346 mixed argument types such as <tt>printf()</tt>. Providing general purpose
347 wrappers to such functions presents special problems (covered shortly).
350 <H2><a name="Varargs_nn6"></a>13.5 Varargs and typemaps</H2>
354 Variable length arguments may be used in typemap specifications. For example:
360 // Get variable length arguments (somehow)
364 %typemap(in) (const char *fmt, ...) {
365 // Multi-argument typemap
371 However, this immediately raises the question of what "type" is actually used
372 to represent <tt>(...)</tt>. For lack of a better alternative, the type of
373 <tt>(...)</tt> is set to <tt>void *</tt>. Since there is no
374 way to dynamically pass arguments to a varargs function (as previously described),
375 the <tt>void *</tt> argument value is intended to serve as a place holder
376 for storing some kind of information about the extra arguments (if any). In addition, the
377 default behavior of SWIG is to pass the <tt>void *</tt> value as an argument to
378 the function. Therefore, you could use the pointer to hold a valid argument value if you wanted.
382 To illustrate, here is a safer version of wrapping <tt>printf()</tt> in Python:
387 %typemap(in) (const char *fmt, ...) {
388 $1 = "%s"; /* Fix format string to %s */
389 $2 = (void *) PyString_AsString($input); /* Get string argument */
392 int printf(const char *fmt, ...);
397 In this example, the format string is implicitly set to <tt>"%s"</tt>.
398 This prevents a program from passing a bogus format string to the
399 extension. Then, the passed input object is decoded and placed in the
400 <tt>void *</tt> argument defined for the <tt>(...)</tt> argument. When the
401 actual function call is made, the underlying wrapper code will look roughly
413 arg2 = (void *) PyString_AsString(arg2obj);
415 result = printf(arg1,arg2);
422 Notice how both arguments are passed to the function and it does what you
427 The next example illustrates a more advanced kind of varargs typemap.
428 Disclaimer: this requires special support in the target language module and is not
429 guaranteed to work with all SWIG modules at this time. It also starts to illustrate
430 some of the more fundamental problems with supporting varargs in more generality.
434 If a typemap is defined for any form of <tt>(...)</tt>, many SWIG
435 modules will generate wrappers that accept a variable number of
436 arguments as input and will make these arguments available in some
437 form. The precise details of this depends on the language module
438 being used (consult the appropriate chapter for more details).
439 However, suppose that you wanted to create a Python wrapper for the
440 <tt>execlp()</tt> function shown earlier. To do this using a typemap
441 instead of using <tt>%varargs</tt>, you might first write a typemap
447 %typemap(in) (...)(char *args[10]) {
450 for (i = 0; i < 10; i++) args[i] = 0;
451 argc = PyTuple_Size(varargs);
453 PyErr_SetString(PyExc_ValueError,"Too many arguments");
456 for (i = 0; i < argc; i++) {
457 PyObject *o = PyTuple_GetItem(varargs,i);
458 if (!PyString_Check(o)) {
459 PyErr_SetString(PyExc_ValueError,"Expected a string");
462 args[i] = PyString_AsString(o);
470 In this typemap, the special variable <tt>varargs</tt> is a tuple
471 holding all of the extra arguments passed (this is specific to the
472 Python module). The typemap then pulls this apart and sticks the
473 values into the array of strings <tt>args</tt>. Then, the array is
474 assigned to <tt>$1</tt> (recall that this is the <tt>void *</tt>
475 variable corresponding to <tt>(...)</tt>). However, this assignment
476 is only half of the picture----clearly this alone is not enough to
477 make the function work. To patch everything up, you have to rewrite the
478 underlying action code using the <tt>%feature</tt> directive like
484 %feature("action") execlp {
485 char *args = (char **) arg3;
486 result = execlp(arg1, arg2, args[0], args[1], args[2], args[3], args[4],
487 args[5],args[6],args[7],args[8],args[9], NULL);
490 int execlp(const char *path, const char *arg, ...);
495 This patches everything up and creates a function that more or less
496 works. However, don't try explaining this to your coworkers unless
497 you know for certain that they've had several cups of coffee. If you
498 really want to elevate your guru status and increase your job
499 security, continue to the next section.
502 <H2><a name="Varargs_nn7"></a>13.6 Varargs wrapping with libffi</H2>
506 All of the previous examples have relied on features of SWIG that are
507 portable and which don't rely upon any low-level machine-level
508 details. In many ways, they have all dodged the real issue of variable
509 length arguments by recasting a varargs function into some weaker variation
510 with a fixed number of arguments of known types. In many cases, this
511 works perfectly fine. However, if you want more generality than this,
512 you need to bring out some bigger guns.
516 One way to do this is to use a special purpose library such as libffi
518 href="http://sources.redhat.com/libffi/">http://sources.redhat.com/libffi</a>).
519 libffi is a library that allows you to dynamically construct
520 call-stacks and invoke procedures in a relatively platform independent
521 manner. Details about the library can be found in the libffi
522 distribution and are not repeated here.
526 To illustrate the use of libffi, suppose that you <em>really</em> wanted to create a
527 wrapper for <tt>execlp()</tt> that accepted <em>any</em> number of
528 arguments. To do this, you might make a few adjustments to the previous
529 example. For example:
534 /* Take an arbitrary number of extra arguments and place into an array
542 argc = PyTuple_Size(varargs);
543 argv = (char **) malloc(sizeof(char *)*(argc+1));
544 for (i = 0; i < argc; i++) {
545 PyObject *o = PyTuple_GetItem(varargs,i);
546 if (!PyString_Check(o)) {
547 PyErr_SetString(PyExc_ValueError,"Expected a string");
551 argv[i] = PyString_AsString(o);
557 /* Rewrite the function call, using libffi */
559 %feature("action") execlp {
566 vc = PyTuple_Size(varargs);
567 types = (ffi_type **) malloc((vc+3)*sizeof(ffi_type *));
568 values = (void **) malloc((vc+3)*sizeof(void *));
569 args = (char **) arg3;
571 /* Set up path parameter */
572 types[0] = &ffi_type_pointer;
573 values[0] = &arg1;
575 /* Set up first argument */
576 types[1] = &ffi_type_pointer;
577 values[1] = &arg2;
579 /* Set up rest of parameters */
580 for (i = 0; i <= vc; i++) {
581 types[2+i] = &ffi_type_pointer;
582 values[2+i] = &args[i];
584 if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+3,
585 &ffi_type_uint, types) == FFI_OK) {
586 ffi_call(&cif, (void (*)()) execlp, &result, values);
588 PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
599 /* Declare the function. Whew! */
600 int execlp(const char *path, const char *arg1, ...);
605 Looking at this example, you may start to wonder if SWIG is making
606 life any easier. Given the amount of code involved, you might also wonder
607 why you didn't just write a hand-crafted wrapper! Either that or you're wondering
608 "why in the hell am I trying to wrap this varargs function in the
609 first place?!?" Obviously, those are questions you'll have to answer for yourself.
613 As a more extreme example of libffi, here is some code that attempts to wrap <tt>printf()</tt>,
618 /* A wrapper for printf() using libffi */
621 /* Structure for holding passed arguments after conversion */
630 enum { VT_INT, VT_DOUBLE, VT_POINTER };
633 %typemap(in) (const char *fmt, ...) {
639 $1 = PyString_AsString($input);
641 /* Variable length arguments */
642 argc = PyTuple_Size(varargs);
643 argv = (vtype *) malloc(argc*sizeof(vtype));
644 for (i = 0; i < argc; i++) {
645 PyObject *o = PyTuple_GetItem(varargs,i);
646 if (PyInt_Check(o)) {
647 argv[i].type = VT_INT;
648 argv[i].val.ivalue = PyInt_AsLong(o);
649 } else if (PyFloat_Check(o)) {
650 argv[i].type = VT_DOUBLE;
651 argv[i].val.dvalue = PyFloat_AsDouble(o);
652 } else if (PyString_Check(o)) {
653 argv[i].type = VT_POINTER;
654 argv[i].val.pvalue = (void *) PyString_AsString(o);
656 PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
664 /* Rewrite the function call using libffi */
665 %feature("action") printf {
672 vc = PyTuple_Size(varargs);
673 types = (ffi_type **) malloc((vc+1)*sizeof(ffi_type *));
674 values = (void **) malloc((vc+1)*sizeof(void *));
675 args = (vtype *) arg2;
677 /* Set up fmt parameter */
678 types[0] = &ffi_type_pointer;
679 values[0] = &arg1;
681 /* Set up rest of parameters */
682 for (i = 0; i < vc; i++) {
683 switch(args[i].type) {
685 types[1+i] = &ffi_type_uint;
686 values[1+i] = &args[i].val.ivalue;
689 types[1+i] = &ffi_type_double;
690 values[1+i] = &args[i].val.dvalue;
693 types[1+i] = &ffi_type_pointer;
694 values[1+i] = &args[i].val.pvalue;
697 abort(); /* Whoa! We're seriously hosed */
701 if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+1,
702 &ffi_type_uint, types) == FFI_OK) {
703 ffi_call(&cif, (void (*)()) printf, &result, values);
705 PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
717 int printf(const char *fmt, ...);
722 Much to your amazement, it even seems to work if you try it:
725 <div class="targetlang">
727 >>> import example
728 >>> example.printf("Grade: %s %d/60 = %0.2f%%\n", "Dave", 47, 47.0*100/60)
729 Grade: Dave 47/60 = 78.33%
735 Of course, there are still some limitations to consider:
738 <div class="targetlang">
740 >>> example.printf("la de da de da %s", 42)
741 Segmentation fault (core dumped)
746 And, on this note, we leave further exploration of libffi to the reader as an exercise. Although Python has been used as an example,
747 most of the techniques in this section can be extrapolated to other language modules with a bit of work. The only
748 details you need to know is how the extra arguments are accessed in each target language. For example, in the Python
749 module, we used the special <tt>varargs</tt> variable to get these arguments. Modules such as Tcl8 and Perl5 simply
750 provide an argument number for the first extra argument. This can be used to index into an array of passed arguments to get
751 values. Please consult the chapter on each language module for more details.
754 <H2><a name="Varargs_nn8"></a>13.7 Wrapping of va_list</H2>
758 Closely related to variable length argument wrapping, you may encounter functions that accept a parameter
759 of type <tt>va_list</tt>. For example:
764 int vfprintf(FILE *f, const char *fmt, va_list ap);
769 As far as we know, there is no obvious way to wrap these functions
770 with SWIG. This is because there is no documented way to assemble the
771 proper va_list structure (there are no C library functions to do it
772 and the contents of va_list are opaque). Not only that, the contents
773 of a <tt>va_list</tt> structure are closely tied to the underlying
774 call-stack. It's not clear that exporting a <tt>va_list</tt> would
775 have any use or that it would work at all.
778 <H2><a name="Varargs_nn9"></a>13.8 C++ Issues</H2>
782 Wrapping of C++ member functions that accept a variable number of
783 arguments presents a number of challenges. By far, the easiest way to
784 handle this is to use the <tt>%varargs</tt> directive. This is portable
785 and it fully supports classes much like the <tt>%rename</tt> directive. For example:
790 %varargs (10, char * = NULL) Foo::bar;
794 virtual void bar(char *arg, ...); // gets varargs above
797 class Spam: public Foo {
799 virtual void bar(char *arg, ...); // gets varargs above
805 <tt>%varargs</tt> also works with constructors, operators, and any
806 other C++ programming construct that accepts variable arguments.
810 Doing anything more advanced than this is likely to involve a serious
811 world of pain. In order to use a library like libffi, you will need
812 to know the underlying calling conventions and details of the C++ ABI. For
813 instance, the details of how <tt>this</tt> is passed to member
814 functions as well as any hidden arguments that might be used to pass
815 additional information. These details are implementation specific and
816 may differ between compilers and even different versions of the same
817 compiler. Also, be aware that invoking a member function is further
818 complicated if it is a virtual method. In this case,
819 invocation might require a table lookup to obtain the proper function address
820 (although you might be able to obtain an address by casting a bound
821 pointer to a pointer to function as described in the C++ ARM section
826 If you do decide to change the underlying action code, be aware that SWIG
827 always places the <tt>this</tt> pointer in <tt>arg1</tt>. Other arguments
828 are placed in <tt>arg2</tt>, <tt>arg3</tt>, and so forth. For example:
833 %feature("action") Foo::bar {
835 result = arg1->bar(arg2, arg3, etc.);
842 Given the potential to shoot yourself in the foot, it is probably easier to reconsider your
843 design or to provide an alternative interface using a helper function than it is to create a
844 fully general wrapper to a varargs C++ member function.
847 <H2><a name="Varargs_nn10"></a>13.9 Discussion</H2>
851 This chapter has provided a number of techniques that can be used to address the problem of variable length
852 argument wrapping. If you care about portability and ease of use, the <tt>%varargs</tt> directive is
853 probably the easiest way to tackle the problem. However, using typemaps, it is possible to do some very advanced
858 One point of discussion concerns the structure of the libffi examples in the previous section. Looking
859 at that code, it is not at all clear that this is the easiest way to solve the problem. However, there
860 are a number of subtle aspects of the solution to consider--mostly concerning the way in which the
861 problem has been decomposed. First, the example is structured in a way that tries to maintain separation
862 between wrapper-specific information and the declaration of the function itself. The idea here is that
863 you might structure your interface like this:
868 %typemap(const char *fmt, ...) {
871 %feature("action") traceprintf {
875 /* Include some header file with traceprintf in it */
876 %include "someheader.h"
881 Second, careful scrutiny will reveal that the typemaps involving <tt>(...)</tt> have nothing
882 whatsoever to do with the libffi library. In fact, they are generic with respect to the way in which
883 the function is actually called. This decoupling means that it will be much easier to consider
884 other library alternatives for making the function call. For instance, if libffi wasn't supported on a certain
885 platform, you might be able to use something else instead. You could use conditional compilation
892 %feature("action") printf {
897 %feature("action") printf {
905 Finally, even though you might be inclined to just write a hand-written wrapper for varargs functions,
906 the techniques used in the previous section have the advantage of being compatible with all other features
907 of SWIG such as exception handling.
911 As a final word, some C programmers seem to have the assumption that
912 the wrapping of variable length argument functions is an easily solved
913 problem. However, this section has hopefully dispelled some of these
914 myths. All things being equal, you are better off avoiding variable
915 length arguments if you can. If you can't avoid them, please consider
916 some of the simple solutions first. If you can't live with a simple
917 solution, proceed with caution. At the very least, make sure you
918 carefully read the section "A7.3.2 Function Calls" in Kernighan and
919 Ritchie and make sure you fully understand the parameter passing conventions used for varargs.
920 Also, be aware of the platform dependencies and reliability issues that
921 this will introduce. Good luck.