问题
So, I got an idea to try to p/invoke C functions that take va_list
. I know how to p/invoke classic varargs functions (with __arglist
), and as it seemed to me that va_list
works just like an ArgIterator
, I thought it might be possible to just pass it to the method:
[DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern int vswprintf(StringBuilder str, int length, string format, ArgIterator args);
public static int vswprintf(StringBuilder str, int length, string format, __arglist)
{
return vswprintf(str, length, format, new ArgIterator(__arglist));
}
int len = 100;
StringBuilder sb = new StringBuilder(len);
vswprintf(sb, len, "%s, %d", __arglist("test", 2));
It turns out that .NET actually recognizes this, because the following exception is thrown:
System.NotSupportedException
in System.StubHelpers.StubHelpers.MarshalToUnmanagedVaListInternal(IntPtr va_list, UInt32 vaListSize, IntPtr pArgIterator)
in Program.vswprintf(StringBuilder str, Int32 length, String format, ArgIterator args)
in Program.vswprintf(StringBuilder str, Int32 length, String format)
So, apparently, .NET knows what I am trying to do and has something that should do it:
[MethodImpl(MethodImplOptions.InternalCall), ForceTokenStabilization]
internal static extern void MarshalToUnmanagedVaListInternal(IntPtr va_list, uint vaListSize, IntPtr pArgIterator); //Reflector
The names of the arguments hint at the purpose, but the exception confuses me. Do I do the p/invoke wrong, or is this .NET marshalling method not finished?
Edit:
After a bit of a research, I've found the implementation of this method and it seems it isn't possible to pass a normal string. So I've modified the code:
vswprintf(sb, len, "%d, %d", __arglist(1, 2));
But this throws an AccessViolationException
(my favourite) instead! What's wrong now?
来源:https://stackoverflow.com/questions/29675018/marshalling-argiterator-to-va-list