Thousands of changes to correct incorrect HTML. HTML is now valid (transitional 4.01).

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6074 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2004-08-04 21:28:14 +00:00
commit aa4d1d907d
31 changed files with 6754 additions and 4801 deletions

View file

@ -5,18 +5,18 @@
</head>
<body bgcolor="#ffffff">
<a name="n1"></a><H1>11 Variable Length Arguments</H1>
<H1><a name="Varargs"></a>13 Variable Length Arguments</H1>
<!-- INDEX -->
<ul>
<li><a href="#n2">Introduction</a>
<li><a href="#n3">The Problem</a>
<li><a href="#n4">Default varargs support</a>
<li><a href="#n5">Argument replacement using %varargs</a>
<li><a href="#n6">Varargs and typemaps</a>
<li><a href="#n7">Varargs wrapping with libffi</a>
<li><a href="#n8">Wrapping of va_list</a>
<li><a href="#n9">C++ Issues</a>
<li><a href="#n10">Discussion</a>
<li><a href="#Varargs_nn2">Introduction</a>
<li><a href="#Varargs_nn3">The Problem</a>
<li><a href="#Varargs_nn4">Default varargs support</a>
<li><a href="#Varargs_nn5">Argument replacement using %varargs</a>
<li><a href="#Varargs_nn6">Varargs and typemaps</a>
<li><a href="#Varargs_nn7">Varargs wrapping with libffi</a>
<li><a href="#Varargs_nn8">Wrapping of va_list</a>
<li><a href="#Varargs_nn9">C++ Issues</a>
<li><a href="#Varargs_nn10">Discussion</a>
</ul>
<!-- INDEX -->
@ -25,18 +25,19 @@
<b>(a.k.a, "The horror. The horror.")</b>
<p>
This chapter describes the problem of wrapping functions that take a
variable number of arguments. For instance, generating wrappers for
the C <tt>printf()</tt> family of functions.
</p>
<p>
This topic is sufficiently advanced to merit its own chapter. In
fact, support for varargs is an often requested feature that was first
added in SWIG-1.3.12. Most other wrapper generation tools have
wisely chosen to avoid this issue.
</p>
<a name="n2"></a><H2>11.1 Introduction</H2>
<H2><a name="Varargs_nn2"></a>13.1 Introduction</H2>
Some C and C++ programs may include functions that accept a variable
@ -74,6 +75,7 @@ list of pointers into which return values are placed. However, variable
length arguments are also sometimes used to write functions that accept a
NULL-terminated list of pointers. A good example of this would
be a function like this:
</p>
<blockquote>
<pre>
@ -122,7 +124,7 @@ List make_list(const char *s, ...) {
</pre>
</blockquote>
<a name="n3"></a><H2>11.2 The Problem</H2>
<H2><a name="Varargs_nn3"></a>13.2 The Problem</H2>
Generating wrappers for a variable length argument function presents a
@ -138,10 +140,12 @@ type <tt>va_list</tt>, this is something entirely different. You
can't take a <tt>va_list</tt> structure and pass it in place of the
variable length arguments to another varargs function. It just
doesn't work.
</p>
<p>
The reason this doesn't work has to do with the way that function
calls get compiled. For example, suppose that your program has a function call like this:
</p>
<blockquote>
<pre>
@ -159,6 +163,7 @@ frame followed by a call to <tt>printf()</tt>.
<p>
In contrast, suppose you attempted to make some kind of wrapper around
<tt>printf()</tt> using code like this:
</p>
<blockquote>
<pre>
@ -188,6 +193,7 @@ worse, you won't know the types and sizes of arguments until run-time
as well. Needless to say, there is no obvious way to make the C
compiler generate code for a function call involving an unknown number
of arguments of unknown types.
</p>
<p>
In theory, it <em>is</em> possible to write a wrapper that does the right thing.
@ -195,6 +201,7 @@ However, this involves knowing the underlying ABI for the target platform and la
as well as writing special purpose code that manually constructed the call stack before
making a procedure call. Unfortunately, both of these tasks require the use of inline
assembly code. Clearly, that's the kind of solution you would much rather avoid.
</p>
<p>
With this nastiness in mind, SWIG provides a number of solutions to the varargs
@ -202,8 +209,9 @@ wrapping problem. Most of these solutions are compromises that provide limited
varargs support without having to resort to assembly language. However, SWIG
can also support real varargs wrapping (with stack-frame manipulation) if you
are willing to get hands dirty. Keep reading.
</p>
<a name="n4"></a><H2>11.3 Default varargs support</H2>
<H2><a name="Varargs_nn4"></a>13.3 Default varargs support</H2>
When variable length arguments appear in an interface, the default
@ -239,14 +247,14 @@ instance, you could make function calls like this (in Python):
<blockquote>
<pre>
>>> traceprintf("Hello World")
>>> traceprintf("Hello %s. Your number is %d\n" % (name, num))
&gt;&gt;&gt; traceprintf("Hello World")
&gt;&gt;&gt; traceprintf("Hello %s. Your number is %d\n" % (name, num))
</pre>
</blockquote>
Notice how string formatting is being done in Python instead of C.
<a name="n5"></a><H2>11.4 Argument replacement using %varargs</H2>
<H2><a name="Varargs_nn5"></a>13.4 Argument replacement using %varargs</H2>
Instead of dropping the variable length arguments, an alternative approach is to replace
@ -292,13 +300,15 @@ known. When replicated argument replacement is used, at least one extra
argument is added to the end of the arguments when making the function call.
This argument serves as a sentinel to make sure the list is properly terminated.
It has the same value as that supplied to the <tt>%varargs</tt> directive.
</p>
<p>
Argument replacement is not as useful when working with functions that accept
mixed argument types such as <tt>printf()</tt>. Providing general purpose
wrappers to such functions presents special problems (covered shortly).
</p>
<a name="n6"></a><H2>11.5 Varargs and typemaps</H2>
<H2><a name="Varargs_nn6"></a>13.5 Varargs and typemaps</H2>
Variable length arguments may be used in typemap specifications. For example:
@ -326,6 +336,7 @@ default behavior of SWIG is to pass the <tt>void *</tt> value as an argument to
the function. Therefore, you could use the pointer to hold a valid argument value if you wanted.
<p>
To illustrate, here is a safer version of wrapping <tt>printf()</tt> in Python:
</p>
<blockquote>
<pre>
@ -369,6 +380,7 @@ The next example illustrates a more advanced kind of varargs typemap.
Disclaimer: this requires special support in the target language module and is not
guaranteed to work with all SWIG modules at this time. It also starts to illustrate
some of the more fundamental problems with supporting varargs in more generality.
</p>
<p>
If a typemap is defined for any form of <tt>(...)</tt>, many SWIG
@ -380,6 +392,7 @@ However, suppose that you wanted to create a Python wrapper for the
<tt>execlp()</tt> function shown earlier. To do this using a typemap
instead of using <tt>%varargs</tt>, you might first write a typemap
like this:
</p>
<blockquote>
<pre>
@ -388,7 +401,7 @@ like this:
int argc;
for (i = 0; i &lt; 10; i++) args[i] = 0;
argc = PyTuple_Size(varargs);
if (argc > 10) {
if (argc &gt; 10) {
PyErr_SetString(PyExc_ValueError,"Too many arguments");
return NULL;
}
@ -427,15 +440,16 @@ this:
int execlp(const char *path, const char *arg, ...);
</pre>
</blockquote>
<p>
<p>
This patches everything up and creates a function that more or less
works. However, don't try explaining this to your coworkers unless
you know for certain that they've had several cups of coffee. If you
really want to elevate your guru status and increase your job
security, continue to the next section.
</p>
<a name="n7"></a><H2>11.6 Varargs wrapping with libffi</H2>
<H2><a name="Varargs_nn7"></a>13.6 Varargs wrapping with libffi</H2>
All of the previous examples have relied on features of SWIG that are
@ -446,7 +460,7 @@ with a fixed number of arguments of known types. In many cases, this
works perfectly fine. However, if you want more generality than this,
you need to bring out some bigger guns.
<P>
<p>
One way to do this is to use a special purpose library such as libffi
(<a
href="http://sources.redhat.com/libffi/">http://sources.redhat.com/libffi</a>).
@ -454,12 +468,14 @@ libffi is a library that allows you to dynamically construct
call-stacks and invoke procedures in a relatively platform independent
manner. Details about the library can be found in the libffi
distribution and are not repeated here.
</p>
<p>
To illustrate the use of libffi, suppose that you <em>really</em> wanted to create a
wrapper for <tt>execlp()</tt> that accepted <em>any</em> number of
arguments. To do this, you might make a few adjustments to the previous
example. For example:
</p>
<blockquote>
<pre>
@ -501,21 +517,21 @@ example. For example:
args = (char **) arg3;
/* Set up path parameter */
types[0] = &ffi_type_pointer;
values[0] = &arg1;
types[0] = &amp;ffi_type_pointer;
values[0] = &amp;arg1;
/* Set up first argument */
types[1] = &ffi_type_pointer;
values[1] = &arg2;
types[1] = &amp;ffi_type_pointer;
values[1] = &amp;arg2;
/* Set up rest of parameters */
for (i = 0; i &lt;= vc; i++) {
types[2+i] = &ffi_type_pointer;
values[2+i] = &args[i];
types[2+i] = &amp;ffi_type_pointer;
values[2+i] = &amp;args[i];
}
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+3,
&ffi_type_uint, types) == FFI_OK) {
ffi_call(&cif, (void (*)()) execlp, &result, values);
if (ffi_prep_cif(&amp;cif, FFI_DEFAULT_ABI, vc+3,
&amp;ffi_type_uint, types) == FFI_OK) {
ffi_call(&amp;cif, (void (*)()) execlp, &amp;result, values);
} else {
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
free(types);
@ -541,6 +557,7 @@ first place?!?" Obviously, those are questions you'll have to answer for yourse
<p>
As a more extreme example of libffi, here is some code that attempts to wrap <tt>printf()</tt>,
</p>
<blockquote>
<pre>
@ -604,32 +621,32 @@ As a more extreme example of libffi, here is some code that attempts to wrap <tt
args = (vtype *) arg2;
/* Set up fmt parameter */
types[0] = &ffi_type_pointer;
values[0] = &arg1;
types[0] = &amp;ffi_type_pointer;
values[0] = &amp;arg1;
/* Set up rest of parameters */
for (i = 0; i &lt; vc; i++) {
switch(args[i].type) {
case VT_INT:
types[1+i] = &ffi_type_uint;
values[1+i] = &args[i].val.ivalue;
types[1+i] = &amp;ffi_type_uint;
values[1+i] = &amp;args[i].val.ivalue;
break;
case VT_DOUBLE:
types[1+i] = &ffi_type_double;
values[1+i] = &args[i].val.dvalue;
types[1+i] = &amp;ffi_type_double;
values[1+i] = &amp;args[i].val.dvalue;
break;
case VT_POINTER:
types[1+i] = &ffi_type_pointer;
values[1+i] = &args[i].val.pvalue;
types[1+i] = &amp;ffi_type_pointer;
values[1+i] = &amp;args[i].val.pvalue;
break;
default:
abort(); /* Whoa! We're seriously hosed */
break;
}
}
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, vc+1,
&ffi_type_uint, types) == FFI_OK) {
ffi_call(&cif, (void (*)()) printf, &result, values);
if (ffi_prep_cif(&amp;cif, FFI_DEFAULT_ABI, vc+1,
&amp;ffi_type_uint, types) == FFI_OK) {
ffi_call(&amp;cif, (void (*)()) printf, &amp;result, values);
} else {
PyErr_SetString(PyExc_RuntimeError, "Whoa!!!!!");
free(types);
@ -651,10 +668,10 @@ Much to your amazement, it even seems to work if you try it:
<blockquote>
<pre>
>>> import example
>>> example.printf("Grade: %s %d/60 = %0.2f%%\n", "Dave", 47, 47.0*100/60)
&gt;&gt;&gt; import example
&gt;&gt;&gt; example.printf("Grade: %s %d/60 = %0.2f%%\n", "Dave", 47, 47.0*100/60)
Grade: Dave 47/60 = 78.33%
>>>
&gt;&gt;&gt;
</pre>
</blockquote>
@ -662,7 +679,7 @@ Of course, there are still some limitations to consider:
<blockquote>
<pre>
>>> example.printf("la de da de da %s", 42)
&gt;&gt;&gt; example.printf("la de da de da %s", 42)
Segmentation fault (core dumped)
</pre>
</blockquote>
@ -674,7 +691,7 @@ module, we used the special <tt>varargs</tt> variable to get these arguments. M
provide an argument number for the first extra argument. This can be used to index into an array of passed arguments to get
values. Please consult the chapter on each language module for more details.
<a name="n8"></a><H2>11.7 Wrapping of va_list</H2>
<H2><a name="Varargs_nn8"></a>13.7 Wrapping of va_list</H2>
Closely related to variable length argument wrapping, you may encounter functions that accept a parameter
@ -694,7 +711,7 @@ of a <tt>va_list</tt> structure are closely tied to the underlying
call-stack. It's not clear that exporting a <tt>va_list</tt> would
have any use or that it would work at all.
<a name="n9"></a><H2>11.8 C++ Issues</H2>
<H2><a name="Varargs_nn9"></a>13.8 C++ Issues</H2>
Wrapping of C++ member functions that accept a variable number of
@ -735,17 +752,19 @@ invocation might require a table lookup to obtain the proper function address
(although you might be able to obtain an address by casting a bound
pointer to a pointer to function as described in the C++ ARM section
18.3.4).
</p>
<p>
If you do decide to change the underlying action code, be aware that SWIG
always places the <tt>this</tt> pointer in <tt>arg1</tt>. Other arguments
are placed in <tt>arg2</tt>, <tt>arg3</tt>, and so forth. For example:
</p>
<blockquote>
<pre>
%feature("action") Foo::bar {
...
result = arg1->bar(arg2, arg3, etc.);
result = arg1-&gt;bar(arg2, arg3, etc.);
...
}
</pre>
@ -755,7 +774,7 @@ Given the potential to shoot yourself in the foot, it is probably easier to reco
design or to provide an alternative interface using a helper function than it is to create a
fully general wrapper to a varargs C++ member function.
<a name="n10"></a><H2>11.9 Discussion</H2>
<H2><a name="Varargs_nn10"></a>13.9 Discussion</H2>
This chapter has provided a number of techniques that can be used to address the problem of variable length
@ -770,6 +789,7 @@ are a number of subtle aspects of the solution to consider--mostly concerning th
problem has been decomposed. First, the example is structured in a way that tries to maintain separation
between wrapper-specific information and the declaration of the function itself. The idea here is that
you might structure your interface like this:
</p>
<blockquote>
<pre>
@ -823,8 +843,9 @@ carefully read the section "A7.3.2 Function Calls" in Kernighan and
Ritchie and make sure you fully understand the parameter passing conventions used for varargs.
Also, be aware of the platform dependencies and reliability issues that
this will introduce. Good luck.
</p>
<p><hr>
<hr>
<address>SWIG 1.3 - Last Modified : March 24, 2002</address>
</body>