[Mono-list] Platform invoke for stdarg

Jonathan Pryor jonpryor@vt.edu
Wed, 17 Nov 2004 07:23:43 -0500


On Tue, 2004-11-16 at 14:13 +0100, Francis Brosnan Blázquez wrote:
> El lun, 15-11-2004 a las 20:54 -0500, Jonathan Pryor escribió:
> > On Mon, 2004-11-15 at 20:24 +0100, Francis Brosnan Blázquez wrote:
> > > Hi,
> > > 
> > > I'm trying to do a P/Invoke call for functions such as 
> > > 
> > > 	void Test(int value, ...); 
> > > 
> > > But I don't get it working. Is it posible to do a platform invoke for c
> > > functions that make use of stdarg api?

<snip/>

> > However, there are two solutions:
> > 
> > 1.  Standard overloading: If there is a "reasonable" number of
> > parameters you need, you can explicitly specify them as overloads.  

<snip/>

> > 2.  Get creative, take an object[] array, and generate some
> > System.Reflection.Emit code which accepts the proper number of
> > parameters of the proper type, and invoke the recently generated code.

<snip/>

It turns out I'm (unfortunately) wrong on both these solutions.  After
talking with lupus on IRC about this, we've determined that these
solutions will work, but only on some platforms.

The solutions above have one thing in common: they rely on an overloaded
function list, where each overload has a fixed number of parameters.
This may be a compile time list (solution 1) or a runtime-generated list
(solution 2), but this list is still present.

The problem is that some platforms, such as AMD64, use a "cookie" as
part of the function call sequence to help prevent buffer overflows and
stack corruption.

Both of the presented solutions don't, and can't, take this cookie into
consideration, and the cookie generated by them will be a value
generated for a fixed number of parameters, not the value required for
the stdarg calling convention.

Platforms which don't have this feature, such as x86 and PPC, will
function with the solutions presented above.

At present, there is NO PORTABLE SOLUTION to calling stdarg functions.
In the future, Mono will support __arglist, which will permit this, but
__arglist will likely be extremely limited, as type marshaling support
may be lacking (which would keep printf(3) from being wrapped, as
strings would need to be marshaled).

A potential workaround would be to create a new C function which accepts
an array instead of "...", and the C function would call the stdarg
function on your behalf.  However, this solution begins to resemble
solution 1, in that the C function would need to somehow convert the
array into a stdarg calling sequence, which would probably involve a
list of C functions which then call the stdarg function...  Not pretty,
in any event, nor entirely general, as I can't think of a decent way to
wrap printf(3) by doing this, either. :-(

 - Jon