Mercurial > hg > vboxdotnet
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/InteropCodeGen/ComInteropProxyGenerator.cs Fri May 06 04:02:43 2011 +0200 @@ -0,0 +1,274 @@ +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); + } + } + } +}