Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / v9 / html / swig / Varargs.html
CommitLineData
920dae64
AT
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2<html>
3<head>
4<title>Variable Length Arguments</title>
5<link rel="stylesheet" type="text/css" href="style.css">
6</head>
7
8<body bgcolor="#ffffff">
9<H1><a name="Varargs"></a>13 Variable Length Arguments</H1>
10<!-- INDEX -->
11<div class="sectiontoc">
12<ul>
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>
22</ul>
23</div>
24<!-- INDEX -->
25
26
27
28<p>
29<b>(a.k.a, "The horror. The horror.")</b>
30</p>
31
32<p>
33This chapter describes the problem of wrapping functions that take a
34variable number of arguments. For instance, generating wrappers for
35the C <tt>printf()</tt> family of functions.
36</p>
37
38<p>
39This topic is sufficiently advanced to merit its own chapter. In
40fact, support for varargs is an often requested feature that was first
41added in SWIG-1.3.12. Most other wrapper generation tools have
42wisely chosen to avoid this issue.
43</p>
44
45<H2><a name="Varargs_nn2"></a>13.1 Introduction</H2>
46
47
48<p>
49Some C and C++ programs may include functions that accept a variable
50number of arguments. For example, most programmers are
51familiar with functions from the C library such as the following:
52</p>
53
54<div class="code">
55<pre>
56int printf(const char *fmt, ...)
57int fprintf(FILE *, const char *fmt, ...);
58int sprintf(char *s, const char *fmt, ...);
59</pre>
60</div>
61
62<p>
63Although there is probably little practical purpose in wrapping these
64specific C library functions in a scripting language (what would be the
65point?), a library may include its own set of special functions based
66on a similar API. For example:
67</p>
68
69<div class="code">
70<pre>
71int traceprintf(const char *fmt, ...);
72</pre>
73</div>
74
75<p>
76In this case, you may want to have some kind of access from the target language.
77</p>
78
79<p>
80Before describing the SWIG implementation, it is important to discuss
81the common uses of varargs that you are likely to encounter in real
82programs. Obviously, there are the <tt>printf()</tt> style output
83functions as shown. Closely related to this would be
84<tt>scanf()</tt> style input functions that accept a format string and a
85list of pointers into which return values are placed. However, variable
86length arguments are also sometimes used to write functions that accept a
87NULL-terminated list of pointers. A good example of this would
88be a function like this:
89</p>
90
91<div class="code">
92<pre>
93int execlp(const char *path, const char *arg1, ...);
94...
95
96/* Example */
97execlp("ls","ls","-l",NULL);
98</pre>
99</div>
100
101<p>
102In addition, varargs is sometimes used to fake default arguments in older
103C libraries. For instance, the low level <tt>open()</tt> system call
104is often declared as a varargs function so that it will accept two
105or three arguments:
106</p>
107
108<div class="code">
109<pre>
110int open(const char *path, int oflag, ...);
111...
112
113/* Examples */
114f = open("foo", O_RDONLY);
115g = open("bar", O_WRONLY | O_CREAT, 0644);
116</pre>
117</div>
118
119<p>
120Finally, to implement a varargs function, recall that you have to use
121the C library functions defined in <tt>&lt;stdarg.h&gt;</tt>. For
122example:
123</p>
124
125<div class="code">
126<pre>
127List make_list(const char *s, ...) {
128 va_list ap;
129 List x;
130 ...
131 va_start(ap, s);
132 while (s) {
133 x.append(s);
134 s = va_arg(ap, const char *);
135 }
136 va_end(ap);
137 return x;
138}
139</pre>
140</div>
141
142<H2><a name="Varargs_nn3"></a>13.2 The Problem</H2>
143
144
145<p>
146Generating wrappers for a variable length argument function presents a
147number of special challenges. Although C provides support for
148implementing functions that receive variable length arguments, there
149are no functions that can go in the other direction. Specifically,
150you can't write a function that dynamically creates a list of
151arguments and which invokes a varargs function on your behalf.
152</p>
153
154<p>
155Although it is possible to write functions that accept the special
156type <tt>va_list</tt>, this is something entirely different. You
157can't take a <tt>va_list</tt> structure and pass it in place of the
158variable length arguments to another varargs function. It just
159doesn't work.
160</p>
161
162<p>
163The reason this doesn't work has to do with the way that function
164calls get compiled. For example, suppose that your program has a function call like this:
165</p>
166
167<div class="code">
168<pre>
169printf("Hello %s. Your number is %d\n", name, num);
170</pre>
171</div>
172
173<p>
174When the compiler looks at this, it knows that you are calling
175<tt>printf()</tt> with exactly three arguments. Furthermore, it knows
176that the number of arguments as well are their types and sizes is
177<em>never</em> going to change during program execution. Therefore,
178this gets turned to machine code that sets up a three-argument stack
179frame followed by a call to <tt>printf()</tt>.
180</p>
181
182<p>
183In contrast, suppose you attempted to make some kind of wrapper around
184<tt>printf()</tt> using code like this:
185</p>
186
187<div class="code">
188<pre>
189int wrap_printf(const char *fmt, ...) {
190 va_list ap;
191 va_start(ap,fmt);
192 ...
193 printf(fmt,ap);
194 ...
195 va_end(ap);
196};
197</pre>
198</div>
199
200<p>
201Athough this code might compile, it won't do what you expect. This is
202because the call to <tt>printf()</tt> is compiled as a procedure call
203involving only two arguments. However, clearly a two-argument
204configuration of the call stack is completely wrong if your intent is
205to pass an arbitrary number of arguments to the real
206<tt>printf()</tt>. Needless to say, it won't work.
207</p>
208
209<p>
210Unfortunately, the situation just described is exactly the problem
211faced by wrapper generation tools. In general, the number of passed
212arguments will not be known until run-time. To make matters even
213worse, you won't know the types and sizes of arguments until run-time
214as well. Needless to say, there is no obvious way to make the C
215compiler generate code for a function call involving an unknown number
216of arguments of unknown types.
217</p>
218
219<p>
220In theory, it <em>is</em> possible to write a wrapper that does the right thing.
221However, this involves knowing the underlying ABI for the target platform and language
222as well as writing special purpose code that manually constructed the call stack before
223making a procedure call. Unfortunately, both of these tasks require the use of inline
224assembly code. Clearly, that's the kind of solution you would much rather avoid.
225</p>
226
227<p>
228With this nastiness in mind, SWIG provides a number of solutions to the varargs
229wrapping problem. Most of these solutions are compromises that provide limited
230varargs support without having to resort to assembly language. However, SWIG
231can also support real varargs wrapping (with stack-frame manipulation) if you
232are willing to get hands dirty. Keep reading.
233</p>
234
235<H2><a name="Varargs_nn4"></a>13.3 Default varargs support</H2>
236
237
238<p>
239When variable length arguments appear in an interface, the default
240behavior is to drop the variable argument list entirely, replacing
241them with a single NULL pointer. For example, if you had this
242function,
243</p>
244
245<div class="code">
246<pre>
247void traceprintf(const char *fmt, ...);
248</pre>
249</div>
250
251<p>
252it would be wrapped as if it had been declared as follows:
253</p>
254
255<div class="code">
256<pre>
257void traceprintf(const char *fmt);
258</pre>
259</div>
260
261<p>
262When the function is called inside the wrappers, it is called as follows:
263</p>
264
265<div class="code">
266<pre>
267traceprintf(arg1, NULL);
268</pre>
269</div>
270
271<p>
272Arguably, this approach seems to defeat the whole point of variable length arguments. However,
273this actually provides enough support for many simple kinds of varargs functions to still be useful. For
274instance, you could make function calls like this (in Python):
275</p>
276
277<div class="targetlang">
278<pre>
279&gt;&gt;&gt; traceprintf("Hello World")
280&gt;&gt;&gt; traceprintf("Hello %s. Your number is %d\n" % (name, num))
281</pre>
282</div>
283
284<p>
285Notice how string formatting is being done in Python instead of C.
286</p>
287
288<H2><a name="Varargs_nn5"></a>13.4 Argument replacement using %varargs</H2>
289
290
291<p>
292Instead 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
294that can be used to do this. For example,
295</p>
296
297<div class="code">
298<pre>
299%varargs(int mode = 0) open;
300...
301int open(const char *path, int oflags, ...);
302</pre>
303</div>
304
305<p>
306is equivalent to this:
307</p>
308
309<div class="code">
310<pre>
311int open(const char *path, int oflags, int mode = 0);
312</pre>
313</div>
314
315<p>
316In this case, <tt>%varargs</tt> is simply providing more specific information about the
317extra arguments that might be passed to a function.
318If the parameters to a varargs function are of uniform type, <tt>%varargs</tt> can also
319accept a numerical argument count as follows:
320</p>
321
322<div class="code">
323<pre>
324%varargs(10,char *arg = NULL) execlp;
325...
326int execlp(const char *path, const char *arg1, ...);
327</pre>
328</div>
329
330<p>
331This would wrap <tt>execlp()</tt> as a function that accepted up to 10 optional arguments.
332Depending on the application, this may be more than enough for practical purposes.
333</p>
334
335<p>
336Argument replacement is most appropriate in cases where the types of
337the extra arguments is uniform and the maximum number of arguments is
338known. When replicated argument replacement is used, at least one extra
339argument is added to the end of the arguments when making the function call.
340This argument serves as a sentinel to make sure the list is properly terminated.
341It has the same value as that supplied to the <tt>%varargs</tt> directive.
342</p>
343
344<p>
345Argument replacement is not as useful when working with functions that accept
346mixed argument types such as <tt>printf()</tt>. Providing general purpose
347wrappers to such functions presents special problems (covered shortly).
348</p>
349
350<H2><a name="Varargs_nn6"></a>13.5 Varargs and typemaps</H2>
351
352
353<p>
354Variable length arguments may be used in typemap specifications. For example:
355</p>
356
357<div class="code">
358<pre>
359%typemap(in) (...) {
360 // Get variable length arguments (somehow)
361 ...
362}
363
364%typemap(in) (const char *fmt, ...) {
365 // Multi-argument typemap
366}
367</pre>
368</div>
369
370<p>
371However, this immediately raises the question of what "type" is actually used
372to 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
374way to dynamically pass arguments to a varargs function (as previously described),
375the <tt>void *</tt> argument value is intended to serve as a place holder
376for storing some kind of information about the extra arguments (if any). In addition, the
377default behavior of SWIG is to pass the <tt>void *</tt> value as an argument to
378the function. Therefore, you could use the pointer to hold a valid argument value if you wanted.
379</p>
380
381<p>
382To illustrate, here is a safer version of wrapping <tt>printf()</tt> in Python:
383</p>
384
385<div class="code">
386<pre>
387%typemap(in) (const char *fmt, ...) {
388 $1 = "%s"; /* Fix format string to %s */
389 $2 = (void *) PyString_AsString($input); /* Get string argument */
390};
391...
392int printf(const char *fmt, ...);
393</pre>
394</div>
395
396<p>
397In this example, the format string is implicitly set to <tt>"%s"</tt>.
398This prevents a program from passing a bogus format string to the
399extension. Then, the passed input object is decoded and placed in the
400<tt>void *</tt> argument defined for the <tt>(...)</tt> argument. When the
401actual function call is made, the underlying wrapper code will look roughly
402like this:
403</p>
404
405<div class="code">
406<pre>
407wrap_printf() {
408 char *arg1;
409 void *arg2;
410 int result;
411
412 arg1 = "%s";
413 arg2 = (void *) PyString_AsString(arg2obj);
414 ...
415 result = printf(arg1,arg2);
416 ...
417}
418</pre>
419</div>
420
421<p>
422Notice how both arguments are passed to the function and it does what you
423would expect.
424</p>
425
426<p>
427The next example illustrates a more advanced kind of varargs typemap.
428Disclaimer: this requires special support in the target language module and is not
429guaranteed to work with all SWIG modules at this time. It also starts to illustrate
430some of the more fundamental problems with supporting varargs in more generality.
431</p>
432
433<p>
434If a typemap is defined for any form of <tt>(...)</tt>, many SWIG
435modules will generate wrappers that accept a variable number of
436arguments as input and will make these arguments available in some
437form. The precise details of this depends on the language module
438being used (consult the appropriate chapter for more details).
439However, suppose that you wanted to create a Python wrapper for the
440<tt>execlp()</tt> function shown earlier. To do this using a typemap
441instead of using <tt>%varargs</tt>, you might first write a typemap
442like this:
443</p>
444
445<div class="code">
446<pre>
447%typemap(in) (...)(char *args[10]) {
448 int i;
449 int argc;
450 for (i = 0; i &lt; 10; i++) args[i] = 0;
451 argc = PyTuple_Size(varargs);
452 if (argc &gt; 10) {
453 PyErr_SetString(PyExc_ValueError,"Too many arguments");
454 return NULL;
455 }
456 for (i = 0; i &lt; argc; i++) {
457 PyObject *o = PyTuple_GetItem(varargs,i);
458 if (!PyString_Check(o)) {
459 PyErr_SetString(PyExc_ValueError,"Expected a string");
460 return NULL;
461 }
462 args[i] = PyString_AsString(o);
463 }
464 $1 = (void *) args;
465}
466</pre>
467</div>
468
469<p>
470In this typemap, the special variable <tt>varargs</tt> is a tuple
471holding all of the extra arguments passed (this is specific to the
472Python module). The typemap then pulls this apart and sticks the
473values into the array of strings <tt>args</tt>. Then, the array is
474assigned to <tt>$1</tt> (recall that this is the <tt>void *</tt>
475variable corresponding to <tt>(...)</tt>). However, this assignment
476is only half of the picture----clearly this alone is not enough to
477make the function work. To patch everything up, you have to rewrite the
478underlying action code using the <tt>%feature</tt> directive like
479this:
480</p>
481
482<div class="code">
483<pre>
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);
488}
489
490int execlp(const char *path, const char *arg, ...);
491</pre>
492</div>
493
494<p>
495This patches everything up and creates a function that more or less
496works. However, don't try explaining this to your coworkers unless
497you know for certain that they've had several cups of coffee. If you
498really want to elevate your guru status and increase your job
499security, continue to the next section.
500</p>
501
502<H2><a name="Varargs_nn7"></a>13.6 Varargs wrapping with libffi</H2>
503
504
505<p>
506All of the previous examples have relied on features of SWIG that are
507portable and which don't rely upon any low-level machine-level
508details. In many ways, they have all dodged the real issue of variable
509length arguments by recasting a varargs function into some weaker variation
510with a fixed number of arguments of known types. In many cases, this
511works perfectly fine. However, if you want more generality than this,
512you need to bring out some bigger guns.
513</p>
514
515<p>
516One way to do this is to use a special purpose library such as libffi
517(<a
518href="http://sources.redhat.com/libffi/">http://sources.redhat.com/libffi</a>).
519libffi is a library that allows you to dynamically construct
520call-stacks and invoke procedures in a relatively platform independent
521manner. Details about the library can be found in the libffi
522distribution and are not repeated here.
523</p>
524
525<p>
526To illustrate the use of libffi, suppose that you <em>really</em> wanted to create a
527wrapper for <tt>execlp()</tt> that accepted <em>any</em> number of
528arguments. To do this, you might make a few adjustments to the previous
529example. For example:
530</p>
531
532<div class="code">
533<pre>
534/* Take an arbitrary number of extra arguments and place into an array
535 of strings */
536
537%typemap(in) (...) {
538 char **argv;
539 int argc;
540 int i;
541
542 argc = PyTuple_Size(varargs);
543 argv = (char **) malloc(sizeof(char *)*(argc+1));
544 for (i = 0; i &lt; argc; i++) {
545 PyObject *o = PyTuple_GetItem(varargs,i);
546 if (!PyString_Check(o)) {
547 PyErr_SetString(PyExc_ValueError,"Expected a string");
548 free(argv);
549 return NULL;
550 }
551 argv[i] = PyString_AsString(o);
552 }
553 argv[i] = NULL;
554 $1 = (void *) argv;
555}
556
557/* Rewrite the function call, using libffi */
558
559%feature("action") execlp {
560 int i, vc;
561 ffi_cif cif;
562 ffi_type **types;
563 void **values;
564 char **args;
565
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;
570
571 /* Set up path parameter */
572 types[0] = &amp;ffi_type_pointer;
573 values[0] = &amp;arg1;
574
575 /* Set up first argument */
576 types[1] = &amp;ffi_type_pointer;
577 values[1] = &amp;arg2;
578
579 /* Set up rest of parameters */
580 for (i = 0; i &lt;= vc; i++) {
581 types[2+i] = &amp;ffi_type_pointer;
582 values[2+i] = &amp;args[i];
583 }
584 if (ffi_prep_cif(&amp;cif, FFI_DEFAULT_ABI, vc+3,
585 &amp;ffi_type_uint, types) == FFI_OK) {
586 ffi_call(&amp;cif, (void (*)()) execlp, &amp;result, values);
587 } else {
588 PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
589 free(types);
590 free(values);
591 free(arg3);
592 return NULL;
593 }
594 free(types);
595 free(values);
596 free(arg3);
597}
598
599/* Declare the function. Whew! */
600int execlp(const char *path, const char *arg1, ...);
601</pre>
602</div>
603
604<p>
605Looking at this example, you may start to wonder if SWIG is making
606life any easier. Given the amount of code involved, you might also wonder
607why 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
609first place?!?" Obviously, those are questions you'll have to answer for yourself.
610</p>
611
612<p>
613As a more extreme example of libffi, here is some code that attempts to wrap <tt>printf()</tt>,
614</p>
615
616<div class="code">
617<pre>
618/* A wrapper for printf() using libffi */
619
620%{
621/* Structure for holding passed arguments after conversion */
622 typedef struct {
623 int type;
624 union {
625 int ivalue;
626 double dvalue;
627 void *pvalue;
628 } val;
629 } vtype;
630 enum { VT_INT, VT_DOUBLE, VT_POINTER };
631%}
632
633%typemap(in) (const char *fmt, ...) {
634 vtype *argv;
635 int argc;
636 int i;
637
638 /* Format string */
639 $1 = PyString_AsString($input);
640
641 /* Variable length arguments */
642 argc = PyTuple_Size(varargs);
643 argv = (vtype *) malloc(argc*sizeof(vtype));
644 for (i = 0; i &lt; 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);
655 } else {
656 PyErr_SetString(PyExc_ValueError,"Unsupported argument type");
657 free(argv);
658 return NULL;
659 }
660 }
661 $2 = (void *) argv;
662}
663
664/* Rewrite the function call using libffi */
665%feature("action") printf {
666 int i, vc;
667 ffi_cif cif;
668 ffi_type **types;
669 void **values;
670 vtype *args;
671
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;
676
677 /* Set up fmt parameter */
678 types[0] = &amp;ffi_type_pointer;
679 values[0] = &amp;arg1;
680
681 /* Set up rest of parameters */
682 for (i = 0; i &lt; vc; i++) {
683 switch(args[i].type) {
684 case VT_INT:
685 types[1+i] = &amp;ffi_type_uint;
686 values[1+i] = &amp;args[i].val.ivalue;
687 break;
688 case VT_DOUBLE:
689 types[1+i] = &amp;ffi_type_double;
690 values[1+i] = &amp;args[i].val.dvalue;
691 break;
692 case VT_POINTER:
693 types[1+i] = &amp;ffi_type_pointer;
694 values[1+i] = &amp;args[i].val.pvalue;
695 break;
696 default:
697 abort(); /* Whoa! We're seriously hosed */
698 break;
699 }
700 }
701 if (ffi_prep_cif(&amp;cif, FFI_DEFAULT_ABI, vc+1,
702 &amp;ffi_type_uint, types) == FFI_OK) {
703 ffi_call(&amp;cif, (void (*)()) printf, &amp;result, values);
704 } else {
705 PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
706 free(types);
707 free(values);
708 free(args);
709 return NULL;
710 }
711 free(types);
712 free(values);
713 free(args);
714}
715
716/* The function */
717int printf(const char *fmt, ...);
718</pre>
719</div>
720
721<p>
722Much to your amazement, it even seems to work if you try it:
723</p>
724
725<div class="targetlang">
726<pre>
727&gt;&gt;&gt; import example
728&gt;&gt;&gt; example.printf("Grade: %s %d/60 = %0.2f%%\n", "Dave", 47, 47.0*100/60)
729Grade: Dave 47/60 = 78.33%
730&gt;&gt;&gt;
731</pre>
732</div>
733
734<p>
735Of course, there are still some limitations to consider:
736</p>
737
738<div class="targetlang">
739<pre>
740&gt;&gt;&gt; example.printf("la de da de da %s", 42)
741Segmentation fault (core dumped)
742</pre>
743</div>
744
745<p>
746And, on this note, we leave further exploration of libffi to the reader as an exercise. Although Python has been used as an example,
747most of the techniques in this section can be extrapolated to other language modules with a bit of work. The only
748details you need to know is how the extra arguments are accessed in each target language. For example, in the Python
749module, we used the special <tt>varargs</tt> variable to get these arguments. Modules such as Tcl8 and Perl5 simply
750provide an argument number for the first extra argument. This can be used to index into an array of passed arguments to get
751values. Please consult the chapter on each language module for more details.
752</p>
753
754<H2><a name="Varargs_nn8"></a>13.7 Wrapping of va_list</H2>
755
756
757<p>
758Closely related to variable length argument wrapping, you may encounter functions that accept a parameter
759of type <tt>va_list</tt>. For example:
760</p>
761
762<div class="code">
763<pre>
764int vfprintf(FILE *f, const char *fmt, va_list ap);
765</pre>
766</div>
767
768<p>
769As far as we know, there is no obvious way to wrap these functions
770with SWIG. This is because there is no documented way to assemble the
771proper va_list structure (there are no C library functions to do it
772and the contents of va_list are opaque). Not only that, the contents
773of a <tt>va_list</tt> structure are closely tied to the underlying
774call-stack. It's not clear that exporting a <tt>va_list</tt> would
775have any use or that it would work at all.
776</p>
777
778<H2><a name="Varargs_nn9"></a>13.8 C++ Issues</H2>
779
780
781<p>
782Wrapping of C++ member functions that accept a variable number of
783arguments presents a number of challenges. By far, the easiest way to
784handle this is to use the <tt>%varargs</tt> directive. This is portable
785and it fully supports classes much like the <tt>%rename</tt> directive. For example:
786</p>
787
788<div class="code">
789<pre>
790%varargs (10, char * = NULL) Foo::bar;
791
792class Foo {
793public:
794 virtual void bar(char *arg, ...); // gets varargs above
795};
796
797class Spam: public Foo {
798public:
799 virtual void bar(char *arg, ...); // gets varargs above
800};
801</pre>
802</div>
803
804<p>
805<tt>%varargs</tt> also works with constructors, operators, and any
806other C++ programming construct that accepts variable arguments.
807</p>
808
809<p>
810Doing anything more advanced than this is likely to involve a serious
811world of pain. In order to use a library like libffi, you will need
812to know the underlying calling conventions and details of the C++ ABI. For
813instance, the details of how <tt>this</tt> is passed to member
814functions as well as any hidden arguments that might be used to pass
815additional information. These details are implementation specific and
816may differ between compilers and even different versions of the same
817compiler. Also, be aware that invoking a member function is further
818complicated if it is a virtual method. In this case,
819invocation 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
821pointer to a pointer to function as described in the C++ ARM section
82218.3.4).
823</p>
824
825<p>
826If you do decide to change the underlying action code, be aware that SWIG
827always places the <tt>this</tt> pointer in <tt>arg1</tt>. Other arguments
828are placed in <tt>arg2</tt>, <tt>arg3</tt>, and so forth. For example:
829</p>
830
831<div class="code">
832<pre>
833%feature("action") Foo::bar {
834 ...
835 result = arg1-&gt;bar(arg2, arg3, etc.);
836 ...
837}
838</pre>
839</div>
840
841<p>
842Given the potential to shoot yourself in the foot, it is probably easier to reconsider your
843design or to provide an alternative interface using a helper function than it is to create a
844fully general wrapper to a varargs C++ member function.
845</p>
846
847<H2><a name="Varargs_nn10"></a>13.9 Discussion</H2>
848
849
850<p>
851This chapter has provided a number of techniques that can be used to address the problem of variable length
852argument wrapping. If you care about portability and ease of use, the <tt>%varargs</tt> directive is
853probably the easiest way to tackle the problem. However, using typemaps, it is possible to do some very advanced
854kinds of wrapping.
855</p>
856
857<p>
858One point of discussion concerns the structure of the libffi examples in the previous section. Looking
859at that code, it is not at all clear that this is the easiest way to solve the problem. However, there
860are a number of subtle aspects of the solution to consider--mostly concerning the way in which the
861problem has been decomposed. First, the example is structured in a way that tries to maintain separation
862between wrapper-specific information and the declaration of the function itself. The idea here is that
863you might structure your interface like this:
864</p>
865
866<div class="code">
867<pre>
868%typemap(const char *fmt, ...) {
869 ...
870}
871%feature("action") traceprintf {
872 ...
873}
874
875/* Include some header file with traceprintf in it */
876%include "someheader.h"
877</pre>
878</div>
879
880<p>
881Second, careful scrutiny will reveal that the typemaps involving <tt>(...)</tt> have nothing
882whatsoever to do with the libffi library. In fact, they are generic with respect to the way in which
883the function is actually called. This decoupling means that it will be much easier to consider
884other library alternatives for making the function call. For instance, if libffi wasn't supported on a certain
885platform, you might be able to use something else instead. You could use conditional compilation
886to control this:
887</p>
888
889<div class="code">
890<pre>
891#ifdef USE_LIBFFI
892%feature("action") printf {
893 ...
894}
895#endif
896#ifdef USE_OTHERFFI
897%feature("action") printf {
898...
899}
900#endif
901</pre>
902</div>
903
904<p>
905Finally, even though you might be inclined to just write a hand-written wrapper for varargs functions,
906the techniques used in the previous section have the advantage of being compatible with all other features
907of SWIG such as exception handling.
908</p>
909
910<p>
911As a final word, some C programmers seem to have the assumption that
912the wrapping of variable length argument functions is an easily solved
913problem. However, this section has hopefully dispelled some of these
914myths. All things being equal, you are better off avoiding variable
915length arguments if you can. If you can't avoid them, please consider
916some of the simple solutions first. If you can't live with a simple
917solution, proceed with caution. At the very least, make sure you
918carefully read the section "A7.3.2 Function Calls" in Kernighan and
919Ritchie and make sure you fully understand the parameter passing conventions used for varargs.
920Also, be aware of the platform dependencies and reliability issues that
921this will introduce. Good luck.
922</p>
923
924</body>
925</html>