I\'m trying to make this work from c#:
C header:
typedef void (LogFunc) (const char *format, va_list args);
Just in case it helps someone, here's a solution for marshaling the arguments. The delegate is declared as:
[UnmanagedFunctionPointer(CallingConvention.Cdecl, SetLastError = true)] // Cdecl is a must
internal delegate void LogFunc(string format, IntPtr argsAddress);
The argsAddress is the unmanaged memory address where the array starts (I think). The format gives the size of the array. Knowing this I can create the managed array and fill it. Pseuso-code:
size <- get size from format
if size = 0 then return
array <- new IntPtr[size]
Marshal.Copy(argsAddress, array, 0, size);
args <- new string[size]
for i = 0 to size-1 do
placeholder <- get the i-th placeholder from format // e.g. "%s"
switch (placeholder)
case "%s": args[i] <- Marshal.PtrToStringAnsi(array[i])
case "%d": args[i] <- array[i].ToString() // i can't explain why the array contains the value, but it does
default: throw exception("todo: handle {placeholder}")
To tell the truth, I'm not sure how this works. It just seems to get the right data. I'm not claiming it is correct though.