comparison InteropCodeGen/ComInteropProxyGenerator.cs @ 7:a7650e26195f default tip

Added support for generating Com Callable Wrappers
author Ivo Smits
date Fri, 06 May 2011 08:12:43 +0200
parents e640ca67b819
children
comparison
equal deleted inserted replaced
6:e640ca67b819 7:a7650e26195f
6 namespace VBoxSDK { 6 namespace VBoxSDK {
7 class ComInteropProxyGenerator { 7 class ComInteropProxyGenerator {
8 public TextWriter Output { get; private set; } 8 public TextWriter Output { get; private set; }
9 public Boolean IncludeInheritedMembers { get; set; } 9 public Boolean IncludeInheritedMembers { get; set; }
10 public String TypeModifiers { get; set; } 10 public String TypeModifiers { get; set; }
11 public Boolean GenerateDelegates { get; set; }
12 public Boolean GenerateVTables { get; set; }
13 public Boolean GenerateProxies { get; set; }
14 public Boolean GenerateCCWs { get; set; }
11 15
12 public ComInteropProxyGenerator(TextWriter output) { 16 public ComInteropProxyGenerator(TextWriter output) {
13 Output = output; 17 Output = output;
18 GenerateDelegates = true;
19 GenerateVTables = true;
20 GenerateProxies = true;
21 GenerateCCWs = true;
14 } 22 }
15 public void WriteLibrary(LibraryInfo lib) { 23 public void WriteLibrary(LibraryInfo lib) {
16 Output.WriteLine("interface IComProxy {"); 24 if (GenerateProxies) {
17 Output.WriteLine("IntPtr ComPointer { get; }"); 25 Output.WriteLine("interface IComProxy {");
18 Output.WriteLine("void AddRef();"); 26 Output.WriteLine("IntPtr ComPointer { get; }");
19 Output.WriteLine("}"); 27 Output.WriteLine("void AddRef();");
28 Output.WriteLine("}");
29 }
30
31 if (GenerateCCWs) {
32 Output.WriteLine("public interface IComCallableWrapper {");
33 Output.WriteLine("Guid IID { get; }");
34 Output.WriteLine("Int32 ReferenceCount { get; set; }");
35 Output.WriteLine("Object Object { get; }");
36 Output.WriteLine("IntPtr Pointer { get; }");
37 Output.WriteLine("}");
38 Output.WriteLine("public unsafe class IUnknown_CCW {");
39 Output.WriteLine("public static Dictionary<IntPtr, IComCallableWrapper> Instances = new Dictionary<IntPtr, IComCallableWrapper>();");
40 Output.WriteLine("public static IUnknown_vtable GetFunctionTable() {");
41 Output.WriteLine("IUnknown_vtable functions;");
42 Output.WriteLine("functions.AddRef = AddRef;");
43 Output.WriteLine("functions.QueryInterface = QueryInterface;");
44 Output.WriteLine("functions.Release = Release;");
45 Output.WriteLine("return functions;");
46 Output.WriteLine("}");
47 Output.WriteLine("public static HRESULT QueryInterface(IntPtr pthis, ref Guid priid, out IntPtr p) {");
48 Output.WriteLine("p = pthis;");
49 Output.WriteLine("if (Instances[pthis].IID != priid) return 1;");
50 Output.WriteLine("Instances[pthis].ReferenceCount++;");
51 Output.WriteLine("return 0;");
52 Output.WriteLine("}");
53 Output.WriteLine("public static HRESULT AddRef(IntPtr pthis) {");
54 Output.WriteLine("Instances[pthis].ReferenceCount++;");
55 Output.WriteLine("return Instances[pthis].ReferenceCount;");
56 Output.WriteLine("}");
57 Output.WriteLine("public static HRESULT Release(IntPtr pthis) {");
58 Output.WriteLine("IComCallableWrapper cw = Instances[pthis];");
59 Output.WriteLine("cw.ReferenceCount--;");
60 Output.WriteLine("if (cw.ReferenceCount == 0) {");
61 Output.WriteLine("Instances.Remove(pthis);");
62 Output.WriteLine("if (cw is IDisposable) (cw as IDisposable).Dispose();");
63 Output.WriteLine("Marshal.FreeCoTaskMem(*(IntPtr*)pthis);");
64 Output.WriteLine("Marshal.FreeCoTaskMem(pthis);");
65 Output.WriteLine("return 0;");
66 Output.WriteLine("} else {");
67 Output.WriteLine("return cw.ReferenceCount;");
68 Output.WriteLine("}");
69 Output.WriteLine("}");
70 Output.WriteLine("}");
71 }
20 foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) { 72 foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) {
21 WriteInterface(intf.Value); 73 WriteInterface(intf.Value);
22 } 74 }
23 } 75 }
24 public void WriteInterface(InterfaceInfo intf) { 76 public void WriteInterface(InterfaceInfo intf) {
27 while (intfp != null) { 79 while (intfp != null) {
28 members.AddRange(intfp.Members); 80 members.AddRange(intfp.Members);
29 intfp = intfp.Extends; 81 intfp = intfp.Extends;
30 }*/ 82 }*/
31 83
32 foreach (InterfaceMemberInfo member in intf.Members) { 84 if (GenerateDelegates) WriteInterfaceDelegates(intf.Name, intf.Members);
85 if (GenerateVTables) WriteInterfaceVTableStructure(intf.Name, intf.Extends, intf.Members);
86 if (GenerateProxies) WriteInterfaceProxyClasses(intf);
87 if (GenerateCCWs) WriteInterfaceCCWClass(intf);
88 }
89 private void WriteInterfaceDelegates(String Name, IEnumerable<InterfaceMemberInfo> Members) {
90 foreach (InterfaceMemberInfo member in Members) {
33 if (member is PropertyInfo) { 91 if (member is PropertyInfo) {
34 PropertyInfo memberi = (PropertyInfo)member; 92 PropertyInfo memberi = (PropertyInfo)member;
35 if (memberi.Gettable) { 93 if (memberi.Gettable) {
36 Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers); 94 Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers);
37 if (memberi.Type is InterfaceTypeInfo) { 95 if (memberi.Type is InterfaceTypeInfo) {
38 Output.WriteLine("out IntPtr value);"); 96 Output.WriteLine("out IntPtr value);");
39 } else { 97 } else {
40 WriteTypeComMarshalAttributes(memberi.Type, null); 98 WriteTypeComMarshalAttributes(memberi.Type, null);
41 Output.WriteLine("out {0} value);", memberi.Type.Name); 99 Output.WriteLine("out {0} value);", memberi.Type.Name);
42 } 100 }
43 } 101 }
44 if (memberi.Settable) { 102 if (memberi.Settable) {
45 Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", intf.Name, memberi.Name, TypeModifiers); 103 Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers);
46 if (memberi.Type is InterfaceTypeInfo) { 104 if (memberi.Type is InterfaceTypeInfo) {
47 Output.WriteLine("IntPtr value);"); 105 Output.WriteLine("IntPtr value);");
48 } else { 106 } else {
49 WriteTypeComMarshalAttributes(memberi.Type, null); 107 WriteTypeComMarshalAttributes(memberi.Type, null);
50 Output.WriteLine("{0} value);", memberi.Type.Name); 108 Output.WriteLine("{0} value);", memberi.Type.Name);
52 } 110 }
53 } else if (member is MethodInfo) { 111 } else if (member is MethodInfo) {
54 MethodInfo memberi = (MethodInfo)member; 112 MethodInfo memberi = (MethodInfo)member;
55 Output.Write("{0} delegate ", TypeModifiers); 113 Output.Write("{0} delegate ", TypeModifiers);
56 Output.Write("HRESULT "); 114 Output.Write("HRESULT ");
57 Output.Write("{0}_{1}_Delegate(IntPtr mThis", intf.Name, memberi.Name); 115 Output.Write("{0}_{1}_Delegate(IntPtr mThis", Name, memberi.Name);
58 foreach (MethodParameterInfo param in memberi.Parameters) { 116 foreach (MethodParameterInfo param in memberi.Parameters) {
59 Output.Write(", "); 117 Output.Write(", ");
60 if (param.Type is InterfaceTypeInfo) { 118 if (param.Type is InterfaceTypeInfo) {
61 if (param.Output && !param.Input) Output.Write("out "); 119 if (param.Output && !param.Input) Output.Write("out ");
62 else if (param.Reference) Output.Write("ref "); 120 else if (param.Reference) Output.Write("ref ");
78 } 136 }
79 } 137 }
80 Output.WriteLine(");"); 138 Output.WriteLine(");");
81 } 139 }
82 } 140 }
83 141 }
84 Output.WriteLine("{1} struct {0}_vtable {{", intf.Name, TypeModifiers); 142 private void WriteInterfaceVTableStructure(String Name, InterfaceInfo Extends, IEnumerable<InterfaceMemberInfo> Members) {
85 if (intf.Extends != null) { 143 Output.WriteLine("{1} struct {0}_vtable {{", Name, TypeModifiers);
86 Output.WriteLine("public {0}_vtable {0};", intf.Extends.Name); 144 if (Extends != null) {
87 } 145 Output.WriteLine("public {0}_vtable {0};", Extends.Name);
88 foreach (InterfaceMemberInfo member in intf.Members) { 146 }
147 foreach (InterfaceMemberInfo member in Members) {
89 if (member is PropertyInfo) { 148 if (member is PropertyInfo) {
90 PropertyInfo memberi = (PropertyInfo)member; 149 PropertyInfo memberi = (PropertyInfo)member;
91 if (memberi.Gettable) { 150 if (memberi.Gettable) {
92 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", intf.Name, memberi.Name); 151 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", Name, memberi.Name);
93 } 152 }
94 if (memberi.Settable) { 153 if (memberi.Settable) {
95 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", intf.Name, memberi.Name); 154 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", Name, memberi.Name);
96 } 155 }
97 } else if (member is MethodInfo) { 156 } else if (member is MethodInfo) {
98 MethodInfo memberi = (MethodInfo)member; 157 MethodInfo memberi = (MethodInfo)member;
99 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", intf.Name, memberi.Name); 158 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", Name, memberi.Name);
100 } 159 }
101 } 160 }
102 Output.WriteLine("}"); 161 Output.WriteLine("}");
103 162 }
104 Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers); 163 private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members) {
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) { 164 foreach (InterfaceMemberInfo member in members) {
135 if (member is PropertyInfo) { 165 if (member is PropertyInfo) {
136 PropertyInfo memberi = (PropertyInfo)member; 166 PropertyInfo memberi = (PropertyInfo)member;
137 if (!memberi.Gettable && !memberi.Settable) continue; 167 if (!memberi.Gettable && !memberi.Settable) continue;
138 Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name); 168 Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name);
139 if (memberi.Gettable) { 169 if (memberi.Gettable) {
140 Output.WriteLine("get {"); 170 Output.WriteLine("get {");
141 if (memberi.Type is InterfaceTypeInfo) { 171 WriteMethodComCall("get_" + memberi.Name, null, memberi.Type);
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("}"); 172 Output.WriteLine("}");
154 } 173 }
155 if (memberi.Settable) { 174 if (memberi.Settable) {
156 Output.WriteLine("set {"); 175 Output.WriteLine("set {");
157 if (memberi.Type is InterfaceTypeInfo) { 176 WriteMethodComCall("set_" + memberi.Name, new MethodParameterInfo(null, memberi.Type, true, false, false));
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("}"); 177 Output.WriteLine("}");
173 } 178 }
174 Output.WriteLine("}"); 179 Output.WriteLine("}");
175 } else if (member is MethodInfo) { 180 } else if (member is MethodInfo) {
176 MethodInfo memberi = (MethodInfo)member; 181 MethodInfo memberi = (MethodInfo)member;
194 Output.Write("ref "); 199 Output.Write("ref ");
195 } 200 }
196 Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name); 201 Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name);
197 } 202 }
198 Output.WriteLine(") {"); 203 Output.WriteLine(") {");
199 if (memberi.ReturnType != null) { 204
200 if (memberi.ReturnType is InterfaceTypeInfo) { 205 WriteMethodComCall(memberi.Name, memberi.Parameters, memberi.ReturnType);
201 Output.WriteLine("IntPtr retval;"); 206
202 } else { 207 Output.WriteLine("}");
203 Output.WriteLine("{0} retval;", memberi.ReturnType.Name); 208 }
204 } 209 }
205 } 210 }
206 foreach (MethodParameterInfo parameter in memberi.Parameters) { 211 private void WriteMethodComCall(String fname, params MethodParameterInfo[] parameters) {
207 if (parameter.Type is InterfaceTypeInfo) { 212 WriteMethodComCall(fname, (IEnumerable<MethodParameterInfo>)parameters, null);
208 Output.WriteLine("IntPtr lp{0};", parameter.Name); 213 }
209 if (parameter.Input) { 214 private void WriteMethodComCall(String fname, IEnumerable<MethodParameterInfo> parameters, TypeInfo returnType) {
210 Output.WriteLine("if (p{0} == null) {{", parameter.Name); 215 if (returnType == null) {
211 Output.WriteLine("lp{0} = IntPtr.Zero;", parameter.Name); 216 } else if (returnType is InterfaceTypeInfo) {
212 Output.WriteLine("}} else if (p{0} is IComProxy) {{", parameter.Name); 217 Output.WriteLine("IntPtr retval;");
213 Output.WriteLine("((IComProxy)p{0}).AddRef();", parameter.Name); 218 } else {
214 Output.WriteLine("lp{0} = ((IComProxy)p{0}).ComPointer;", parameter.Name); 219 Output.WriteLine("{0} retval;", returnType.Name);
215 Output.WriteLine("} else {"); 220 }
216 Output.WriteLine("lp{0} = Marshal.GetIUnknownForObject(p{0});", parameter.Name); 221
217 Output.WriteLine("}"); 222 if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
223 if (parameter.Type is InterfaceTypeInfo) {
224 String pname = parameter.Name;
225 if (pname == null) {
226 pname = "value";
227 } else {
228 pname = "p" + pname;
229 }
230 Output.WriteLine("IntPtr l{0};", pname);
231 if (parameter.Input) {
232 Output.WriteLine("if ({0} == null) {{", pname);
233 Output.WriteLine("l{0} = IntPtr.Zero;", pname);
234 Output.WriteLine("}} else if ({0} is IComProxy) {{", pname);
235 Output.WriteLine("((IComProxy){0}).AddRef();", pname);
236 Output.WriteLine("l{0} = ((IComProxy){0}).ComPointer;", pname);
237 Output.WriteLine("} else {");
238 if (parameter.Type.Name == "IFramebuffer") {
239 Output.WriteLine("l{0} = (new {1}_CCW({0})).Pointer;", pname, parameter.Type.Name);
240 } else {
241 Output.WriteLine("l{0} = Marshal.GetIUnknownForObject({0});", pname);
218 } 242 }
219 } 243 Output.WriteLine("}");
220 } 244 }
221 245 }
222 Output.Write("HRESULT hr = functions{1}.{0}(pointer", memberi.Name, ftprefix); 246 }
247
248 Output.Write("HRESULT hr = functions.{0}(Pointer", fname);
249 if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
250 Output.Write(", ");
251 if (parameter.Output && !parameter.Input) {
252 Output.Write("out ");
253 } else if (parameter.Reference) {
254 Output.Write("ref ");
255 }
256 String pname = parameter.Name;
257 if (pname == null) {
258 pname = "value";
259 } else {
260 pname = "p" + pname;
261 }
262 if (parameter.Type is InterfaceTypeInfo) {
263 pname = "l" + pname;
264 }
265 Output.Write(pname);
266 }
267 if (returnType != null) {
268 Output.Write(", out retval");
269 }
270 Output.WriteLine(");");
271 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
272
273 if (parameters != null) foreach (MethodParameterInfo parameter in parameters) {
274 if (parameter.Type is InterfaceTypeInfo) {
275 if (parameter.Output) {
276 Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name);
277 }
278 }
279 }
280
281 if (returnType == null) {
282 } else if (returnType is InterfaceTypeInfo) {
283 Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", returnType.Name);
284 } else {
285 Output.WriteLine("return retval;");
286 }
287 }
288 private void WriteInterfaceProxyClasses(InterfaceInfo intf) {
289 if (intf.Extends != null) {
290 Output.WriteLine("{1} unsafe class {0}_Proxy : {2}_Proxy, {0} {{", intf.Name, TypeModifiers, intf.Extends.Name);
291 Output.WriteLine("public new static Guid IID = new Guid(\"{0}\");", intf.IID);
292 } else {
293 Output.WriteLine("{1} unsafe class {0}_Proxy : IComProxy, {0} {{", intf.Name, TypeModifiers);
294 Output.WriteLine("public IntPtr Pointer { get; protected set; }");
295 Output.WriteLine("IntPtr IComProxy.ComPointer { get { return Pointer; } }");
296 Output.WriteLine("public static Guid IID = new Guid(\"{0}\");", intf.IID);
297 }
298 Output.WriteLine("private {0}_vtable functions;", intf.Name);
299
300 Output.WriteLine("public {0}_Proxy(IntPtr p) : this(p, IID) {{ }}", intf.Name);
301
302 if (intf.Extends != null) {
303 Output.WriteLine("public {0}_Proxy(IntPtr p, Guid iid) : base(p, iid) {{", intf.Name, intf.Extends.Name);
304 Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)Pointer, typeof({0}_vtable));", intf.Name);
305 Output.WriteLine("}");
306 } else {
307 Output.WriteLine("public {0}_Proxy(IntPtr p, Guid iid) {{", intf.Name);
308 Output.WriteLine("IUnknown_vtable ft = (IUnknown_vtable)Marshal.PtrToStructure(*(IntPtr*)p, typeof(IUnknown_vtable));");
309 Output.WriteLine("HRESULT hr = ft.QueryInterface(p, ref iid, out p);");
310 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);");
311 Output.WriteLine("ft.AddRef(p);");
312 Output.WriteLine("Pointer = p;");
313 Output.WriteLine("functions = ({0}_vtable)Marshal.PtrToStructure(*(IntPtr*)Pointer, typeof({0}_vtable));", intf.Name);
314 Output.WriteLine("}");
315 }
316
317 if (intf.Name == "IUnknown") {
318 Output.Write("~{0}_Proxy() {{ functions.Release(Pointer); }}", intf.Name);
319 }
320
321 WriteInterfaceMembers(intf.Members);
322 Output.WriteLine("}");
323 }
324 private void WriteInterfaceCCWClass(InterfaceInfo intf) {
325 if (intf.Extends == null) return;
326 Boolean writeMembers = true;
327 if (intf.Name == "IDispatch" || intf.Name == "IErrorInfo") writeMembers = false;
328 Output.WriteLine("public unsafe class {0}_CCW : IComCallableWrapper {{", intf.Name);
329 Output.WriteLine("public IntPtr Pointer { get; protected set; }");
330 Output.WriteLine("public Object Object { get; private set; }");
331 Output.WriteLine("public Int32 ReferenceCount { get; set; }");
332 Output.WriteLine("Guid IComCallableWrapper.IID {{ get {{ return {0}_Proxy.IID; }} }}", intf.Name);
333
334 Output.WriteLine("public static {0}_vtable GetFunctionTable() {{", intf.Name);
335 Output.WriteLine("{0}_vtable functions = new {0}_vtable();", intf.Name);
336 if (writeMembers) foreach (InterfaceMemberInfo member in intf.Members) {
337 if (member is PropertyInfo) {
338 PropertyInfo memberi = (PropertyInfo)member;
339 if (memberi.Gettable) Output.WriteLine("functions.get_{0} = get_{0};", memberi.Name);
340 if (memberi.Settable) Output.WriteLine("functions.set_{0} = set_{0};", memberi.Name);
341 } else if (member is MethodInfo) {
342 MethodInfo memberi = (MethodInfo)member;
343 Output.WriteLine("functions.{0} = {0};", memberi.Name);
344 }
345 }
346 if (intf.Extends != null) Output.WriteLine("functions.{0} = {0}_CCW.GetFunctionTable();", intf.Extends.Name);
347 Output.WriteLine("return functions;");
348 Output.WriteLine("}");
349
350 Output.WriteLine("public {0}_CCW({0} p) {{", intf.Name);
351 Output.WriteLine("Object = p;");
352 Output.WriteLine("Pointer = Marshal.AllocCoTaskMem(IntPtr.Size);");
353 Output.WriteLine("*(IntPtr*)Pointer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof({0}_vtable)));", intf.Name);
354 Output.WriteLine("Marshal.StructureToPtr(GetFunctionTable(), *(IntPtr*)Pointer, false);");
355 Output.WriteLine("IUnknown_CCW.Instances[Pointer] = this;");
356 Output.WriteLine("}");
357 Output.WriteLine("private static {0} GetInstance(IntPtr pthis) {{", intf.Name);
358 Output.WriteLine("return ({0})IUnknown_CCW.Instances[pthis].Object;", intf.Name);
359 Output.WriteLine("}");
360
361 if (writeMembers) foreach (InterfaceMemberInfo member in intf.Members) {
362 if (member is PropertyInfo) {
363 PropertyInfo memberi = (PropertyInfo)member;
364 if (memberi.Gettable) {
365 Output.Write("private static HRESULT get_{0}(IntPtr pthis, out ", memberi.Name);
366 if (memberi.Type is InterfaceTypeInfo) {
367 Output.Write("IntPtr");
368 } else {
369 Output.Write(memberi.Type.Name);
370 }
371 Output.WriteLine(" ret) {");
372 if (memberi.Type is InterfaceTypeInfo) {
373 Output.WriteLine("{1} iret = GetInstance(pthis).{0};", memberi.Name, memberi.Type.Name);
374 Output.WriteLine("if (iret == null) { ret = IntPtr.Zero; } else if (iret is IComProxy) { ret = ((IComProxy)iret).ComPointer; } else {");
375 Output.WriteLine("ret = (new {0}_CCW(iret)).Pointer; }}", memberi.Type.Name);
376 } else {
377 Output.WriteLine("ret = GetInstance(pthis).{0};", memberi.Name);
378 }
379 Output.WriteLine("return 0;");
380 Output.WriteLine("}");
381 }
382 if (memberi.Settable) {
383 Output.Write("private static HRESULT set_{0}(IntPtr pthis, ", memberi.Name);
384 if (memberi.Type is InterfaceTypeInfo) {
385 Output.Write("IntPtr");
386 } else {
387 Output.Write(memberi.Type.Name);
388 }
389 Output.WriteLine(" value) {");
390 if (memberi.Type is InterfaceTypeInfo) {
391 Output.WriteLine("{0} ivalue;", memberi.Type.Name);
392 Output.WriteLine("if (value == IntPtr.Zero) { ivalue = null; } else if (IUnknown_CCW.Instances.ContainsKey(value)) { ivalue = ({0})(IUnknown_CCW.Instances[value].Object) } else { ivalue = new {0}_CCW(value); }", memberi.Type.Name);
393 Output.WriteLine("GetInstance(pthis).{0} = ivalue;", memberi.Name);
394 } else {
395 Output.WriteLine("GetInstance(pthis).{0} = value;", memberi.Name);
396 }
397 Output.WriteLine("return 0;");
398 Output.WriteLine("}");
399 }
400 } else if (member is MethodInfo) {
401 MethodInfo memberi = (MethodInfo)member;
402 Output.Write("private static HRESULT {0}(IntPtr pthis", memberi.Name);
223 foreach (MethodParameterInfo parameter in memberi.Parameters) { 403 foreach (MethodParameterInfo parameter in memberi.Parameters) {
224 Output.Write(", "); 404 Output.Write(", ");
225 if (parameter.Output && !parameter.Input) { 405 if (parameter.Output && !parameter.Input) {
226 Output.Write("out "); 406 Output.Write("out ");
227 } else if (parameter.Reference) { 407 } else if (parameter.Reference) {
228 Output.Write("ref "); 408 Output.Write("ref ");
229 } 409 }
230 if (parameter.Type is InterfaceTypeInfo) { 410 if (parameter.Type is InterfaceTypeInfo) {
231 Output.Write("lp{0}", parameter.Name); 411 Output.Write("IntPtr");
232 } else { 412 } else {
233 Output.Write("p{0}", parameter.Name); 413 Output.Write(parameter.Type.Name);
234 } 414 }
235 } 415 Output.Write(" p{0}", parameter.Name);
236 if (memberi.ReturnType != null) Output.Write(", out retval"); 416 }
237 Output.WriteLine(");"); 417 if (memberi.ReturnType != null) {
238 Output.WriteLine("Marshal.ThrowExceptionForHR(hr);"); 418 Output.Write(", out ");
419 if (memberi.ReturnType is InterfaceTypeInfo) {
420 Output.Write("IntPtr");
421 } else {
422 Output.Write(memberi.ReturnType.Name);
423 }
424 Output.Write(" retval");
425 }
426 Output.WriteLine(") {");
239 427
240 foreach (MethodParameterInfo parameter in memberi.Parameters) { 428 foreach (MethodParameterInfo parameter in memberi.Parameters) {
241 if (parameter.Type is InterfaceTypeInfo) { 429 if (parameter.Type is InterfaceTypeInfo) {
242 if (parameter.Output) { 430 Output.WriteLine("{0} i{1};", parameter.Type.Name, parameter.Name);
243 Output.WriteLine("p{0} = lp{0} == IntPtr.Zero ? null : new {1}_Proxy(lp{0});", parameter.Name, parameter.Type.Name); 431 if (parameter.Input) {
432 Output.WriteLine("if (p{0} == IntPtr.Zero) {{ i{0} = null; }} else if (IUnknown_CCW.Instances.ContainsKey(p{0})) {{ i{0} = ({1})(IUnknown_CCW.Instances[p{0}].Object); }} else {{ i{0} = new {1}_Proxy(p{0}); }}", parameter.Name, parameter.Type.Name);
244 } 433 }
245 } 434 }
246 } 435 }
247 436
248 if (memberi.ReturnType != null) { 437 if (memberi.ReturnType != null) {
249 if (memberi.ReturnType is InterfaceTypeInfo) { 438 if (memberi.ReturnType is InterfaceTypeInfo) {
250 Output.WriteLine("return retval == IntPtr.Zero ? null : new {0}_Proxy(retval);", memberi.ReturnType.Name); 439 Output.Write("{0} iretval = ", memberi.ReturnType.Name);
251 } else { 440 } else {
252 Output.WriteLine("return retval;"); 441 Output.Write("retval = ");
253 } 442 }
254 } 443 }
444 Output.Write("GetInstance(pthis).{0}(", memberi.Name);
445 bool first = true;
446 foreach (MethodParameterInfo parameter in memberi.Parameters) {
447 if (first) {
448 first = false;
449 } else {
450 Output.Write(", ");
451 }
452 if (parameter.Output && !parameter.Input) {
453 Output.Write("out ");
454 } else if (parameter.Reference) {
455 Output.Write("ref ");
456 }
457 if (parameter.Type is InterfaceTypeInfo) {
458 Output.Write("i{0}", parameter.Name);
459 } else {
460 Output.Write("p{0}", parameter.Name);
461 }
462 }
463 Output.WriteLine(");");
464
465 foreach (MethodParameterInfo parameter in memberi.Parameters) {
466 if (parameter.Type is InterfaceTypeInfo) {
467 if (parameter.Output || parameter.Reference) {
468 Output.WriteLine("if (i{0} == null) {{ p{0} = IntPtr.Zero; }} else if (i{0} is IComProxy) {{ p{0} = ((IComProxy)i{0}).ComPointer; }} else {{", parameter.Name);
469 Output.WriteLine("p{1} = (new {0}_CCW(i{1})).Pointer; }}", parameter.Type.Name, parameter.Name);
470 }
471 }
472 }
473 if (memberi.ReturnType is InterfaceTypeInfo) {
474 Output.WriteLine("if (iretval == null) { retval = IntPtr.Zero; } else if (iretval is IComProxy) { retval = ((IComProxy)iretval).ComPointer; } else {");
475 Output.WriteLine("retval = (new {0}_CCW(iretval)).Pointer; }}", memberi.ReturnType.Name);
476 }
477
478 Output.WriteLine("return 0;");
255 Output.WriteLine("}"); 479 Output.WriteLine("}");
256 } 480 }
257 } 481 }
258 } 482 Output.WriteLine("}");
483 }
484
259 public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) { 485 public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) {
260 if (type == null) return; 486 if (type == null) return;
261 String MarshalAs = null; 487 String MarshalAs = null;
262 if (type is InterfaceTypeInfo) { 488 if (type is InterfaceTypeInfo) {
263 MarshalAs = "Interface"; 489 MarshalAs = "Interface";