Mercurial > hg > vboxdotnet
annotate 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 |
rev | line source |
---|---|
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
1 ???using System; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
2 using System.Collections.Generic; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
3 using System.Text; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
4 using System.IO; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
5 |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
6 namespace VBoxSDK { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
7 class ComInteropProxyGenerator { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
8 public TextWriter Output { get; private set; } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
9 public Boolean IncludeInheritedMembers { get; set; } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
10 public String TypeModifiers { get; set; } |
7 | 11 public Boolean GenerateDelegates { get; set; } |
12 public Boolean GenerateVTables { get; set; } | |
13 public Boolean GenerateProxies { get; set; } | |
14 public Boolean GenerateCCWs { get; set; } | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
15 |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
16 public ComInteropProxyGenerator(TextWriter output) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
17 Output = output; |
7 | 18 GenerateDelegates = true; |
19 GenerateVTables = true; | |
20 GenerateProxies = true; | |
21 GenerateCCWs = true; | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
22 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
23 public void WriteLibrary(LibraryInfo lib) { |
7 | 24 if (GenerateProxies) { |
25 Output.WriteLine("interface IComProxy {"); | |
26 Output.WriteLine("IntPtr ComPointer { get; }"); | |
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 } | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
72 foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
73 WriteInterface(intf.Value); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
74 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
75 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
76 public void WriteInterface(InterfaceInfo intf) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
77 /*List<InterfaceMemberInfo> members = new List<InterfaceMemberInfo>(); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
78 InterfaceInfo intfp = intf.Value; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
79 while (intfp != null) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
80 members.AddRange(intfp.Members); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
81 intfp = intfp.Extends; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
82 }*/ |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
83 |
7 | 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) { | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
91 if (member is PropertyInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
92 PropertyInfo memberi = (PropertyInfo)member; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
93 if (memberi.Gettable) { |
7 | 94 Output.Write("{2} delegate HRESULT {0}_{1}_get_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
95 if (memberi.Type is InterfaceTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
96 Output.WriteLine("out IntPtr value);"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
97 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
98 WriteTypeComMarshalAttributes(memberi.Type, null); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
99 Output.WriteLine("out {0} value);", memberi.Type.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
100 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
101 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
102 if (memberi.Settable) { |
7 | 103 Output.Write("{2} delegate HRESULT {0}_{1}_set_Delegate(IntPtr pThis, ", Name, memberi.Name, TypeModifiers); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
104 if (memberi.Type is InterfaceTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
105 Output.WriteLine("IntPtr value);"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
106 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
107 WriteTypeComMarshalAttributes(memberi.Type, null); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
108 Output.WriteLine("{0} value);", memberi.Type.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
109 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
110 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
111 } else if (member is MethodInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
112 MethodInfo memberi = (MethodInfo)member; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
113 Output.Write("{0} delegate ", TypeModifiers); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
114 Output.Write("HRESULT "); |
7 | 115 Output.Write("{0}_{1}_Delegate(IntPtr mThis", Name, memberi.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
116 foreach (MethodParameterInfo param in memberi.Parameters) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
117 Output.Write(", "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
118 if (param.Type is InterfaceTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
119 if (param.Output && !param.Input) Output.Write("out "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
120 else if (param.Reference) Output.Write("ref "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
121 Output.Write("IntPtr p{0}", param.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
122 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
123 WriteTypeComMarshalAttributes(param.Type, null); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
124 if (param.Output && !param.Input) Output.Write("out "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
125 else if (param.Reference) Output.Write("ref "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
126 Output.Write("{0} p{1}", param.Type.Name, param.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
127 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
128 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
129 if (memberi.ReturnType != null) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
130 Output.Write(", "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
131 if (memberi.ReturnType is InterfaceTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
132 Output.Write("out IntPtr mOut"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
133 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
134 WriteTypeComMarshalAttributes(memberi.ReturnType, null); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
135 Output.Write("out {0} mOut", memberi.ReturnType.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
136 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
137 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
138 Output.WriteLine(");"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
139 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
140 } |
7 | 141 } |
142 private void WriteInterfaceVTableStructure(String Name, InterfaceInfo Extends, IEnumerable<InterfaceMemberInfo> Members) { | |
143 Output.WriteLine("{1} struct {0}_vtable {{", Name, TypeModifiers); | |
144 if (Extends != null) { | |
145 Output.WriteLine("public {0}_vtable {0};", Extends.Name); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
146 } |
7 | 147 foreach (InterfaceMemberInfo member in Members) { |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
148 if (member is PropertyInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
149 PropertyInfo memberi = (PropertyInfo)member; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
150 if (memberi.Gettable) { |
7 | 151 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_get_Delegate get_{1};", Name, memberi.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
152 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
153 if (memberi.Settable) { |
7 | 154 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_set_Delegate set_{1};", Name, memberi.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
155 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
156 } else if (member is MethodInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
157 MethodInfo memberi = (MethodInfo)member; |
7 | 158 Output.WriteLine("[MarshalAs(UnmanagedType.FunctionPtr)] public {0}_{1}_Delegate {1};", Name, memberi.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
159 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
160 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
161 Output.WriteLine("}"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
162 } |
7 | 163 private void WriteInterfaceMembers(ICollection<InterfaceMemberInfo> members) { |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
164 foreach (InterfaceMemberInfo member in members) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
165 if (member is PropertyInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
166 PropertyInfo memberi = (PropertyInfo)member; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
167 if (!memberi.Gettable && !memberi.Settable) continue; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
168 Output.WriteLine("public {0} {1} {{", memberi.Type.Name, memberi.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
169 if (memberi.Gettable) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
170 Output.WriteLine("get {"); |
7 | 171 WriteMethodComCall("get_" + memberi.Name, null, memberi.Type); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
172 Output.WriteLine("}"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
173 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
174 if (memberi.Settable) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
175 Output.WriteLine("set {"); |
7 | 176 WriteMethodComCall("set_" + memberi.Name, new MethodParameterInfo(null, memberi.Type, true, false, false)); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
177 Output.WriteLine("}"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
178 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
179 Output.WriteLine("}"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
180 } else if (member is MethodInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
181 MethodInfo memberi = (MethodInfo)member; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
182 Output.Write("public "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
183 if (memberi.ReturnType == null) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
184 Output.Write("void"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
185 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
186 Output.Write(memberi.ReturnType.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
187 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
188 Output.Write(" {0}(", memberi.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
189 Boolean first = true; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
190 foreach (MethodParameterInfo parameter in memberi.Parameters) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
191 if (first) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
192 first = false; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
193 } else { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
194 Output.Write(", "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
195 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
196 if (parameter.Output && !parameter.Input) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
197 Output.Write("out "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
198 } else if (parameter.Reference) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
199 Output.Write("ref "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
200 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
201 Output.Write("{0} p{1}", parameter.Type.Name, parameter.Name); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
202 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
203 Output.WriteLine(") {"); |
7 | 204 |
205 WriteMethodComCall(memberi.Name, memberi.Parameters, memberi.ReturnType); | |
206 | |
207 Output.WriteLine("}"); | |
208 } | |
209 } | |
210 } | |
211 private void WriteMethodComCall(String fname, params MethodParameterInfo[] parameters) { | |
212 WriteMethodComCall(fname, (IEnumerable<MethodParameterInfo>)parameters, null); | |
213 } | |
214 private void WriteMethodComCall(String fname, IEnumerable<MethodParameterInfo> parameters, TypeInfo returnType) { | |
215 if (returnType == null) { | |
216 } else if (returnType is InterfaceTypeInfo) { | |
217 Output.WriteLine("IntPtr retval;"); | |
218 } else { | |
219 Output.WriteLine("{0} retval;", returnType.Name); | |
220 } | |
221 | |
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"; | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
227 } else { |
7 | 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); | |
242 } | |
243 Output.WriteLine("}"); | |
244 } | |
245 } | |
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); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
277 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
278 } |
7 | 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); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
370 } |
7 | 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("}"); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
381 } |
7 | 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); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
403 foreach (MethodParameterInfo parameter in memberi.Parameters) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
404 Output.Write(", "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
405 if (parameter.Output && !parameter.Input) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
406 Output.Write("out "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
407 } else if (parameter.Reference) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
408 Output.Write("ref "); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
409 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
410 if (parameter.Type is InterfaceTypeInfo) { |
7 | 411 Output.Write("IntPtr"); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
412 } else { |
7 | 413 Output.Write(parameter.Type.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
414 } |
7 | 415 Output.Write(" p{0}", parameter.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
416 } |
7 | 417 if (memberi.ReturnType != null) { |
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(") {"); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
427 |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
428 foreach (MethodParameterInfo parameter in memberi.Parameters) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
429 if (parameter.Type is InterfaceTypeInfo) { |
7 | 430 Output.WriteLine("{0} i{1};", parameter.Type.Name, parameter.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); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
433 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
434 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
435 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
436 |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
437 if (memberi.ReturnType != null) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
438 if (memberi.ReturnType is InterfaceTypeInfo) { |
7 | 439 Output.Write("{0} iretval = ", memberi.ReturnType.Name); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
440 } else { |
7 | 441 Output.Write("retval = "); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
442 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
443 } |
7 | 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;"); | |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
479 Output.WriteLine("}"); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
480 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
481 } |
7 | 482 Output.WriteLine("}"); |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
483 } |
7 | 484 |
6
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
485 public void WriteTypeComMarshalAttributes(TypeInfo type, String paramType) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
486 if (type == null) return; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
487 String MarshalAs = null; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
488 if (type is InterfaceTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
489 MarshalAs = "Interface"; |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
490 } else if (type is StringTypeInfo) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
491 MarshalAs = (type as StringTypeInfo).UnmanagedType.ToString(); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
492 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
493 if (MarshalAs != null) { |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
494 Output.Write("["); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
495 if (paramType != null) Output.Write("{0}: ", paramType); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
496 Output.Write("MarshalAs(UnmanagedType.{0})] ", MarshalAs); |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
497 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
498 } |
e640ca67b819
Added extended COM interop code generator for interfaces and proxies
Ivo Smits
parents:
diff
changeset
|
499 } |
7 | 500 } |