Mercurial > hg > vboxdotnet
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"; |