[Mono-list] Platform invoke for stdarg
Jonathan Pryor
jonpryor@vt.edu
Mon, 15 Nov 2004 20:54:22 -0500
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?
No, and Maybe. :-)
There is no general way to marshal "..." parameters, which requires that
all the parameters be passed on the stack -- the Cdecl calling
convention. The .NET marshaller can only work with a fixed number of
arguments.
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. I do
this in Mono.Posix to wrap open(2):
DllImport ("libc", CallingConvention=CallingConvention.Cdecl)
public static extern int open (string pathname, int flags);
DllImport ("libc", CallingConvention=CallingConvention.Cdecl)
public static extern int open (string pathname, int flags, uint mode);
If you plan on using this code on Windows, you *must* specify
CallingCOnvention.Cdecl, as the default is Stdcall, which doesn't permit
variable argument lists.
Obviously, this is only viable if you have a limited number of potential
overloads. Wrapping printf(3) is impractical, as it could result in
hundreds (thousands?) of overloads.
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.
IIRC cocoa-sharp does something similar to this for its msg_send
implementation. Pro: it works for any argument list. Con: it's not
easy.
- Jon