comparison 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
comparison
equal deleted inserted replaced
5:00fb4879d273 6:e640ca67b819
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.IO;
5
6 namespace VBoxSDK {
7 class ComInteropProxyGenerator {
8 public TextWriter Output { get; private set; }
9 public Boolean IncludeInheritedMembers { get; set; }
10 public String TypeModifiers { get; set; }
11
12 public ComInteropProxyGenerator(TextWriter output) {
13 Output = output;
14 }
15 public void WriteLibrary(LibraryInfo lib) {
16 Output.WriteLine("interface IComProxy {");
17 Output.WriteLine("IntPtr ComPointer { get; }");
18 Output.WriteLine("void AddRef();");
19 Output.WriteLine("}");
20 foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) {
21 WriteInterface(intf.Value);
22 }
23 }
24 public void WriteInterface(InterfaceInfo intf) {
25 /*List<InterfaceMemberInfo> members = new List<InterfaceMemberInfo>();
26 InterfaceInfo intfp = intf.Value;
27 while (intfp != null) {
28 members.AddRange(intfp.Members);
29 intfp = intfp.Extends;
30 }*/
31
32 foreach (InterfaceMemberInfo member in intf.Members) {
33 if (member is PropertyInfo) {
34 PropertyInfo memberi = (PropertyInfo)member;
35 if (memberi.Gettable) {
36 Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers);
37 if (memberi.Type is InterfaceTypeInfo) {
38 Output.WriteLine("out IntPtr value);");
39 } else {
40 WriteTypeComMarshalAttributes(memberi.Type, null);
41 Output.WriteLine("out {0} value);", memberi.Type.Name);
42 }
43 }
44 if (memberi.Settable) {
45 Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers);
46 if (memberi.Type is InterfaceTypeInfo) {
47 Output.WriteLine("IntPtr value);");
48 } else {
49 WriteTypeComMarshalAttributes(memberi.Type, null);
50 Output.WriteLine("{0} value);", memberi.Type.Name);
51 }
52 }
53 } else if (member is MethodInfo) {
54 MethodInfo memberi = (MethodInfo)member;
55 Output.Write("{0} delegate ", TypeModifiers);
56 Output.Write("HRESULT ");
57 Output.Write("{0}_{1}_Delegate(IntPtr mThis", intf.Name, memberi.Name);
58 foreach (MethodParameterInfo param in memberi.Parameters) {
59 Output.Write(", ");
60 if (param.Type is InterfaceTypeInfo) {
61 if (param.Output && !param.Input) Output.Write("out ");
62 else if (param.Reference) Output.Write("ref ");
63 Output.Write("IntPtr p{0}", param.Name);
64 } else {
65 WriteTypeComMarshalAttributes(param.Type, null);
66 if (param.Output && !param.Input) Output.Write("out ");
67 else if (param.Reference) Output.Write("ref ");
68 Output.Write("{0} p{1}", param.Type.Name, param.Name);
69 }
70 }
71 if (memberi.ReturnType != null) {
72 Output.Write(", ");
73 if (memberi.ReturnType is InterfaceTypeInfo) {
74 Output.Write("out IntPtr mOut");
75 } else {
76 WriteTypeComMarshalAttributes(memberi.ReturnType, null);
77 Output.Write("out {0} mOut", memberi.ReturnType.Name);
78 }
79 }
80 Output.WriteLine(");");
81 }
82 }
83
84 Output.WriteLine("{1} struct {0}_vtable {{", intf.Name, TypeModifiers);
85 if (intf.Extends != null) {
86 Output.WriteLine("public {0}_vtable {0};", intf.Extends.Name);
87 }
88 foreach (InterfaceMemberInfo member in intf.Members) {
89 if (member is PropertyInfo) {
90 PropertyInfo memberi = (PropertyInfo)member;
91 if (memberi.Gettable) {
92 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", intf.Name, memberi.Name);
93 }
94 if (memberi.Settable) {
95 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", intf.Name, memberi.Name);
96 }
97 } else if (member is MethodInfo) {
98 MethodInfo memberi = (MethodInfo)member;
99 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", intf.Name, memberi.Name);
100 }
101 }
102 Output.WriteLine("}");
103
104 Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers);
105 Output.WriteLine("public static Guid IID = new Guid(\"{0}\");", intf.IID);
106 Output.WriteLine("private IntPtr pointer;");
107 Output.WriteLine("private {0}_vtable functions;", intf.Name);
108 Output.WriteLine("public {0}_Proxy(IntPtr p) {{", intf.Name);
109 Output.WriteLine("IUnknown_vtable ft = (IUnknown_vtable)Marshal.PtrToStructure(*(IntPtr*)p, typeof(IUnknown_vtable));");
110 Output.WriteLine("Guid IIDCopy = IID;");
111 Output.WriteLine("HRESULT hr = ft.QueryInterface(p, ref IIDCopy, out pointer);");
112 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
113 //Output.WriteLine("ft.AddRef(p);");
114 Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)pointer, typeof({0}_vtable));", intf.Name);
115 Output.WriteLine("}");
116 Output.WriteLine("IntPtr IComProxy.ComPointer { get { return pointer; } }");
117 Output.Write("~{0}_Proxy() {{ functions", intf.Name);
118 {
119 InterfaceInfo intfp = intf;
120 while (intfp.Extends != null && intfp.Name != "IUnknown") {
121 intfp = intfp.Extends;
122 Output.Write(".{0}", intfp.Name);
123 }
124 }
125 Output.WriteLine(".Release(pointer); }");
126 WriteInterfaceMembers(intf, "");
127 Output.WriteLine("}");
128 }
129 private void WriteInterfaceMembers(InterfaceInfo intf, String ftprefix) {
130 if (intf.Extends != null) WriteInterfaceMembers(intf.Extends, ftprefix + "." + intf.Extends.Name);
131 WriteInterfaceMembers(intf.Members, ftprefix);
132 }
133 private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members, String ftprefix) {
134 foreach (InterfaceMemberInfo member in members) {
135 if (member is PropertyInfo) {
136 PropertyInfo memberi = (PropertyInfo)member;
137 if (!memberi.Gettable && !memberi.Settable) continue;
138 Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name);
139 if (memberi.Gettable) {
140 Output.WriteLine("get {");
141 if (memberi.Type is InterfaceTypeInfo) {
142 Output.WriteLine("IntPtr value;");
143 } else {
144 Output.WriteLine("{0} value;", memberi.Type.Name);
145 }
146 Output.WriteLine("HRESULT hr = functions{1}.get_{0}(pointer, out value);", memberi.Name, ftprefix);
147 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
148 if (memberi.Type is InterfaceTypeInfo) {
149 Output.WriteLine("return value == IntPtr.Zero ? null : new {0}_Proxy(value);", memberi.Type.Name);
150 } else {
151 Output.WriteLine("return value;");
152 }
153 Output.WriteLine("}");
154 }
155 if (memberi.Settable) {
156 Output.WriteLine("set {");
157 if (memberi.Type is InterfaceTypeInfo) {
158 Output.WriteLine("IntPtr pvalue;");
159 Output.WriteLine("if (pvalue == null) {");
160 Output.WriteLine("pvalue = IntPtr.Zero;");
161 Output.WriteLine("} else if (pvalue is IComProxy) {");
162 Output.WriteLine("((IComProxy)value).AddRef();");
163 Output.WriteLine("pvalue = ((IComProxy)value).ComPointer;");
164 Output.WriteLine("} else {");
165 Output.WriteLine("pvalue = Marshal.GetIUnknownForObject(value);");
166 Output.WriteLine("}");
167 Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, pvalue);", memberi.Name, ftprefix);
168 } else {
169 Output.WriteLine("HRESULT hr = functions{1}.set_{0}(pointer, value);", memberi.Name, ftprefix);
170 }
171 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
172 Output.WriteLine("}");
173 }
174 Output.WriteLine("}");
175 } else if (member is MethodInfo) {
176 MethodInfo memberi = (MethodInfo)member;
177 Output.Write("public ");
178 if (memberi.ReturnType == null) {
179 Output.Write("void");
180 } else {
181 Output.Write(memberi.ReturnType.Name);
182 }
183 Output.Write(" {0}(", memberi.Name);
184 Boolean first = true;
185 foreach (MethodParameterInfo parameter in memberi.Parameters) {
186 if (first) {
187 first = false;
188 } else {
189 Output.Write(", ");
190 }
191 if (parameter.Output && !parameter.Input) {
192 Output.Write("out ");
193 } else if (parameter.Reference) {
194 Output.Write("ref ");
195 }
196 Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name);
197 }
198 Output.WriteLine(") {");
199 if (memberi.ReturnType != null) {
200 if (memberi.ReturnType is InterfaceTypeInfo) {
201 Output.WriteLine("IntPtr retval;");
202 } else {
203 Output.WriteLine("{0} retval;", memberi.ReturnType.Name);
204 }
205 }
206 foreach (MethodParameterInfo parameter in memberi.Parameters) {
207 if (parameter.Type is InterfaceTypeInfo) {
208 Output.WriteLine("IntPtr lp{0};", parameter.Name);
209 if (parameter.Input) {
210 Output.WriteLine("if (p{0} == null) {{", parameter.Name);
211 Output.WriteLine("lp{0} = IntPtr.Zero;", parameter.Name);
212 Output.WriteLine("}} else if (p{0} is IComProxy) {{", parameter.Name);
213 Output.WriteLine("((IComProxy)p{0}).AddRef();", parameter.Name);
214 Output.WriteLine("lp{0} = ((IComProxy)p{0}).ComPointer;", parameter.Name);
215 Output.WriteLine("} else {");
216 Output.WriteLine("lp{0} = Marshal.GetIUnknownForObject(p{0});", parameter.Name);
217 Output.WriteLine("}");
218 }
219 }
220 }
221
222 Output.Write("HRESULT hr = functions{1}.{0}(pointer", memberi.Name, ftprefix);
223 foreach (MethodParameterInfo parameter in memberi.Parameters) {
224 Output.Write(", ");
225 if (parameter.Output && !parameter.Input) {
226 Output.Write("out ");
227 } else if (parameter.Reference) {
228 Output.Write("ref ");
229 }
230 if (parameter.Type is InterfaceTypeInfo) {
231 Output.Write("lp{0}", parameter.Name);
232 } else {
233 Output.Write("p{0}", parameter.Name);
234 }
235 }
236 if (memberi.ReturnType != null) Output.Write(", out retval");
237 Output.WriteLine(");");
238 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
239
240 foreach (MethodParameterInfo parameter in memberi.Parameters) {
241 if (parameter.Type is InterfaceTypeInfo) {
242 if (parameter.Output) {
243 Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name);
244 }
245 }
246 }
247
248 if (memberi.ReturnType != null) {
249 if (memberi.ReturnType is InterfaceTypeInfo) {
250 Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", memberi.ReturnType.Name);
251 } else {
252 Output.WriteLine("return retval;");
253 }
254 }
255 Output.WriteLine("}");
256 }
257 }
258 }
259 public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) {
260 if (type == null) return;
261 String MarshalAs = null;
262 if (type is InterfaceTypeInfo) {
263 MarshalAs = "Interface";
264 } else if (type is StringTypeInfo) {
265 MarshalAs = (type as StringTypeInfo).UnmanagedType.ToString();
266 }
267 if (MarshalAs != null) {
268 Output.Write("[");
269 if (paramType != null) Output.Write("{0}: ", paramType);
270 Output.Write("MarshalAs(UnmanagedType.{0})] ", MarshalAs);
271 }
272 }
273 }
274 }