Mercurial > hg > vboxdotnet
view InteropCodeGen/ComInteropProxyGenerator.cs @ 6:e640ca67b819
Added extended COM interop code generator for interfaces and proxies
author | Ivo Smits |
---|---|
date | Fri, 06 May 2011 04:02:43 +0200 |
parents | |
children | a7650e26195f |
line wrap: on
line source
???using System; using System.Collections.Generic; using System.Text; using System.IO; namespace VBoxSDK { class ComInteropProxyGenerator { public TextWriter Output { get; private set; } public Boolean IncludeInheritedMembers { get; set; } public String TypeModifiers { get; set; } public ComInteropProxyGenerator(TextWriter output) { Output = output; } public void WriteLibrary(LibraryInfo lib) { Output.WriteLine("interface IComProxy {"); Output.WriteLine("IntPtr ComPointer { get; }"); Output.WriteLine("void AddRef();"); Output.WriteLine("}"); foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) { WriteInterface(intf.Value); } } public void WriteInterface(InterfaceInfo intf) { /*List<InterfaceMemberInfo> members = new List<InterfaceMemberInfo>(); InterfaceInfo intfp = intf.Value; while (intfp != null) { members.AddRange(intfp.Members); intfp = intfp.Extends; }*/ foreach (InterfaceMemberInfo member in intf.Members) { if (member is PropertyInfo) { PropertyInfo memberi = (PropertyInfo)member; if (memberi.Gettable) { Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers); if (memberi.Type is InterfaceTypeInfo) { Output.WriteLine("out IntPtr value);"); } else { WriteTypeComMarshalAttributes(memberi.Type, null); Output.WriteLine("out {0} value);", memberi.Type.Name); } } if (memberi.Settable) { Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers); if (memberi.Type is InterfaceTypeInfo) { Output.WriteLine("IntPtr value);"); } else { WriteTypeComMarshalAttributes(memberi.Type, null); Output.WriteLine("{0} value);", memberi.Type.Name); } } } else if (member is MethodInfo) { MethodInfo memberi = (MethodInfo)member; Output.Write("{0} delegate ", TypeModifiers); Output.Write("HRESULT "); Output.Write("{0}_{1}_Delegate(IntPtr mThis", intf.Name, memberi.Name); foreach (MethodParameterInfo param in memberi.Parameters) { Output.Write(", "); if (param.Type is InterfaceTypeInfo) { if (param.Output && !param.Input) Output.Write("out "); else if (param.Reference) Output.Write("ref "); Output.Write("IntPtr p{0}", param.Name); } else { WriteTypeComMarshalAttributes(param.Type, null); if (param.Output && !param.Input) Output.Write("out "); else if (param.Reference) Output.Write("ref "); Output.Write("{0} p{1}", param.Type.Name, param.Name); } } if (memberi.ReturnType != null) { Output.Write(", "); if (memberi.ReturnType is InterfaceTypeInfo) { Output.Write("out IntPtr mOut"); } else { WriteTypeComMarshalAttributes(memberi.ReturnType, null); Output.Write("out {0} mOut", memberi.ReturnType.Name); } } Output.WriteLine(");"); } } Output.WriteLine("{1} struct {0}_vtable {{", intf.Name, TypeModifiers); if (intf.Extends != null) { Output.WriteLine("public {0}_vtable {0};", intf.Extends.Name); } foreach (InterfaceMemberInfo member in intf.Members) { if (member is PropertyInfo) { PropertyInfo memberi = (PropertyInfo)member; if (memberi.Gettable) { Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", intf.Name, memberi.Name); } if (memberi.Settable) { Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", intf.Name, memberi.Name); } } else if (member is MethodInfo) { MethodInfo memberi = (MethodInfo)member; Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", intf.Name, memberi.Name); } } Output.WriteLine("}"); Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers); Output.WriteLine("public static Guid IID = new Guid(\"{0}\");", intf.IID); Output.WriteLine("private IntPtr pointer;"); Output.WriteLine("private {0}_vtable functions;", intf.Name); Output.WriteLine("public {0}_Proxy(IntPtr p) {{", intf.Name); Output.WriteLine("IUnknown_vtable ft = (IUnknown_vtable)Marshal.PtrToStructure(*(IntPtr*)p, typeof(IUnknown_vtable));"); Output.WriteLine("Guid IIDCopy = IID;"); Output.WriteLine("HRESULT hr = ft.QueryInterface(p, ref IIDCopy, out pointer);"); Output.WriteLine("Marshal.ThrowExceptionForHR(hr);"); //Output.WriteLine("ft.AddRef(p);"); Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)pointer, typeof({0}_vtable));", intf.Name); Output.WriteLine("}"); Output.WriteLine("IntPtr IComProxy.ComPointer { get { return pointer; } }"); Output.Write("~{0}_Proxy() {{ functions", intf.Name); { InterfaceInfo intfp = intf; while (intfp.Extends != null && intfp.Name != "IUnknown") { intfp = intfp.Extends; Output.Write(".{0}", intfp.Name); } } Output.WriteLine(".Release(pointer); }"); WriteInterfaceMembers(intf, ""); Output.WriteLine("}"); } private void WriteInterfaceMembers(InterfaceInfo intf, String ftprefix) { if (intf.Extends != null) WriteInterfaceMembers(intf.Extends, ftprefix + "." + intf.Extends.Name); WriteInterfaceMembers(intf.Members, ftprefix); } private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members, String ftprefix) { foreach (InterfaceMemberInfo member in members) { if (member is PropertyInfo) { PropertyInfo memberi = (PropertyInfo)member; if (!memberi.Gettable && !memberi.Settable) continue; Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name); if (memberi.Gettable) { Output.WriteLine("get {"); if (memberi.Type is InterfaceTypeInfo) { Output.WriteLine("IntPtr value;"); } else { Output.WriteLine("{0} value;", memberi.Type.Name); } Output.WriteLine("HRESULT hr = functions{1}.get_{0}(pointer, out value);", memberi.Name, ftprefix); Output.WriteLine("Marshal.ThrowExceptionForHR(hr);"); if (memberi.Type is InterfaceTypeInfo) { Output.WriteLine("return value == IntPtr.Zero ? null : new {0}_Proxy(value);", memberi.Type.Name); } else { Output.WriteLine("return value;"); } Output.WriteLine("}"); } if (memberi.Settable) { Output.WriteLine("set {"); if (memberi.Type is InterfaceTypeInfo) { Output.WriteLine("IntPtr pvalue;"); Output.WriteLine("if (pvalue == null) {"); Output.WriteLine("pvalue = IntPtr.Zero;"); Output.WriteLine("} else if (pvalue is IComProxy) {"); Output.WriteLine("((IComProxy)value).AddRef();"); Output.WriteLine("pvalue = ((IComProxy)value).ComPointer;"); Output.WriteLine("} else {"); Output.WriteLine("pvalue = Marshal.GetIUnknownForObject(value);"); Output.WriteLine("}"); Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, pvalue);", memberi.Name, ftprefix); } else { Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, value);", memberi.Name, ftprefix); } Output.WriteLine("Marshal.ThrowExceptionForHR(hr);"); Output.WriteLine("}"); } Output.WriteLine("}"); } else if (member is MethodInfo) { MethodInfo memberi = (MethodInfo)member; Output.Write("public "); if (memberi.ReturnType == null) { Output.Write("void"); } else { Output.Write(memberi.ReturnType.Name); } Output.Write(" {0}(", memberi.Name); Boolean first = true; foreach (MethodParameterInfo parameter in memberi.Parameters) { if (first) { first = false; } else { Output.Write(", "); } if (parameter.Output && !parameter.Input) { Output.Write("out "); } else if (parameter.Reference) { Output.Write("ref "); } Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name); } Output.WriteLine(") {"); if (memberi.ReturnType != null) { if (memberi.ReturnType is InterfaceTypeInfo) { Output.WriteLine("IntPtr retval;"); } else { Output.WriteLine("{0} retval;", memberi.ReturnType.Name); } } foreach (MethodParameterInfo parameter in memberi.Parameters) { if (parameter.Type is InterfaceTypeInfo) { Output.WriteLine("IntPtr lp{0};", parameter.Name); if (parameter.Input) { Output.WriteLine("if (p{0} == null) {{", parameter.Name); Output.WriteLine("lp{0} = IntPtr.Zero;", parameter.Name); Output.WriteLine("}} else if (p{0} is IComProxy) {{", parameter.Name); Output.WriteLine("((IComProxy)p{0}).AddRef();", parameter.Name); Output.WriteLine("lp{0} = ((IComProxy)p{0}).ComPointer;", parameter.Name); Output.WriteLine("} else {"); Output.WriteLine("lp{0} = Marshal.GetIUnknownForObject(p{0});", parameter.Name); Output.WriteLine("}"); } } } Output.Write("HRESULT hr = functions{1}.{0}(pointer", memberi.Name, ftprefix); foreach (MethodParameterInfo parameter in memberi.Parameters) { Output.Write(", "); if (parameter.Output && !parameter.Input) { Output.Write("out "); } else if (parameter.Reference) { Output.Write("ref "); } if (parameter.Type is InterfaceTypeInfo) { Output.Write("lp{0}", parameter.Name); } else { Output.Write("p{0}", parameter.Name); } } if (memberi.ReturnType != null) Output.Write(", out retval"); Output.WriteLine(");"); Output.WriteLine("Marshal.ThrowExceptionForHR(hr);"); foreach (MethodParameterInfo parameter in memberi.Parameters) { if (parameter.Type is InterfaceTypeInfo) { if (parameter.Output) { Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name); } } } if (memberi.ReturnType != null) { if (memberi.ReturnType is InterfaceTypeInfo) { Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", memberi.ReturnType.Name); } else { Output.WriteLine("return retval;"); } } Output.WriteLine("}"); } } } public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) { if (type == null) return; String MarshalAs = null; if (type is InterfaceTypeInfo) { MarshalAs = "Interface"; } else if (type is StringTypeInfo) { MarshalAs = (type as StringTypeInfo).UnmanagedType.ToString(); } if (MarshalAs != null) { Output.Write("["); if (paramType != null) Output.Write("{0}: ", paramType); Output.Write("MarshalAs(UnmanagedType.{0})] ", MarshalAs); } } } }