private static IntPtr DoCreateBuffer(string encoding) { IntPtr buffer; switch (encoding) { case "c": case "C": buffer = Marshal.AllocHGlobal(4); // note that libffi expects buffers to be at least as big as a word break; case "s": case "S": buffer = Marshal.AllocHGlobal(4); break; case "i": case "I": case "l": case "L": buffer = Marshal.AllocHGlobal(4); break; case "q": case "Q": buffer = Marshal.AllocHGlobal(8); break; case "f": buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(float))); break; case "d": buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double))); break; case "v": case "Vv": buffer = IntPtr.Zero; break; case "@": case "@?": case "#": case ":": buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); break; default: char type = DoGetEncodingType(encoding); if (type == '^' || type == '*' || type == '[' || type == '(') // xxx*, char*, array, union { buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); } else if (type == '{') { int i = encoding.IndexOf('='); if (i >= 0) { string sname = encoding.Substring(1, i - 1); Type stype; if (TypeEncoder.TryGetStruct(sname, out stype)) { int bytes = Marshal.SizeOf(stype); buffer = Marshal.AllocHGlobal(bytes); } else { throw new InvalidCallException("Don't know how to marshal " + sname + " to a native type. Is it marked with RegisterAttribute?"); } } else { throw new InvalidCallException("'" + encoding + "' doesn't have a struct name."); } } else { throw new InvalidCallException("Don't know how to marshal " + encoding + " to a native type."); } break; } return(buffer); }
// Return an ffi_type* which will be used when values of the encoding // type are marshaled through libffi. public static IntPtr GetFfiType(Type type) { string encoding = TypeEncoder.Encode(type); return(DoGetFfiType(encoding)); }