所以,我有一个想法尝试p /调用带va_list
的C函数。我知道如何调用经典的varargs函数(使用__arglist
),并且在我看来va_list
就像ArgIterator
一样,我认为可能只是通过它的方法:
[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));
事实证明,.NET实际上认识到了这一点,因为引发了以下异常:
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)
所以,显然,.NET知道我想做什么,并且有一些应该做的事情:
[MethodImpl(MethodImplOptions.InternalCall), ForceTokenStabilization]
internal static extern void MarshalToUnmanagedVaListInternal(IntPtr va_list, uint vaListSize, IntPtr pArgIterator); //Reflector
参数的名称暗示了目的,但异常让我感到困惑。我是否对p / invoke做错了,或者这个.NET编组方法没有完成?
编辑:
经过一番研究后,我发现了这种方法的implementation,似乎无法传递正常的字符串。所以我修改了代码:
vswprintf(sb, len, "%d, %d", __arglist(1, 2));
但这会引发AccessViolationException
(我最喜欢的)!现在怎么了?