Mercurial > hg > vboxdotnet
comparison InteropCodeGen/XidlParser.cs @ 6:e640ca67b819
Added extended COM interop code generator for interfaces and proxies
author | Ivo Smits |
---|---|
date | Fri, 06 May 2011 04:02:43 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:00fb4879d273 | 6:e640ca67b819 |
---|---|
1 using System; | |
2 using System.Xml.XPath; | |
3 using System.IO; | |
4 using System.Collections.Generic; | |
5 | |
6 namespace VBoxSDK { | |
7 public class XidlParser { | |
8 public LibraryInfo Library { get; private set; } | |
9 public TypeInfo UnknownType { get; set; } | |
10 public InterfaceInfo BaseInterfaceType { get; set; } | |
11 public InterfaceInfo ErrorInterfaceType { get; set; } | |
12 enum ParameterType { | |
13 In, | |
14 Out, | |
15 Reference, | |
16 Return, | |
17 Param, | |
18 } | |
19 public Dictionary<String, TypeInfo> Types = new Dictionary<string, TypeInfo>(); | |
20 | |
21 void AddInterfaceTypes(params String[] names) { | |
22 foreach (String name in names) Types.Add(name, new InterfaceTypeInfo(name)); | |
23 } | |
24 void AddEnumTypes(params String[] names) { | |
25 foreach (String name in names) Types.Add(name, new ValueTypeInfo(name)); | |
26 } | |
27 void InitTypes() { | |
28 Types.Add("short", new ValueTypeInfo(typeof(Int32))); | |
29 Types.Add("unsigned short", new ValueTypeInfo(typeof(UInt16))); | |
30 Types.Add("unsigned long", new ValueTypeInfo(typeof(UInt32))); | |
31 Types.Add("long long", new ValueTypeInfo(typeof(Int64))); | |
32 Types.Add("long", new ValueTypeInfo(typeof(Int32))); | |
33 Types.Add("octet", new ValueTypeInfo(typeof(Byte))); | |
34 Types.Add("unsigned long long", new ValueTypeInfo(typeof(UInt32))); | |
35 //Types.Add("boolean", new TypeInfo("Boolean", "MarshalAs(UnmanagedType.Bool)")); | |
36 Types.Add("boolean", new ValueTypeInfo(typeof(Int32))); | |
37 //Types.Add("wstring", new ValueTypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)")); | |
38 //Types.Add("uuid", new TypeInfo("Guid", true, "MarshalAs(UnmanagedType.LPStruct)")); | |
39 //Types.Add("uuid", new ValueTypeInfo("Guid", "MarshalAs(UnmanagedType.LPStruct)")); | |
40 Types.Add("wstring", new StringTypeInfo()); | |
41 | |
42 Types.Add("$unknown", new ValueTypeInfo(typeof(IntPtr))); | |
43 AddInterfaceTypes("IMachine", "ISession", "IVirtualBox", "IHost", "IConsole", "ISystemProperties"); | |
44 AddInterfaceTypes("IProgress", "IDisplay", "IMouse", "IKeyboard", "IFramebuffer", "IFramebufferOverlay"); | |
45 AddInterfaceTypes("IMachineDebugger", "IVirtualBoxErrorInfo", "IEventSource", "IEventListener", "IEventContext"); | |
46 AddInterfaceTypes("IConsoleCallback", "IEvent", "IBandwidthControl", "IVRDEServerInfo", "IAdditionsFacility"); | |
47 AddInterfaceTypes("IExtPackPlugIn", "IExtPackFile", "IExtPack", "IBIOSSettings", "IVFSExplorer", "IUSBController"); | |
48 AddInterfaceTypes("IStorageController", "IVRDPServer", "ISnapshot", "INATEngine", "IUSBDeviceFilter"); | |
49 AddInterfaceTypes("IMediumAttachment", "IUSBDevice", "IParallelPort", "ISerialPort", "INetworkAdapter"); | |
50 AddInterfaceTypes("IMedium", "IGuestOSType", "ISharedFolder", "IPerformanceCollector", "IDHCPServer"); | |
51 AddInterfaceTypes("IAppliance", "IVirtualBoxCallback", "IPerformanceMetric", "IMediumFormat", "IHostUSBDevice"); | |
52 AddInterfaceTypes("IHostNetworkInterface", "IHostUSBDeviceFilter", "IRemoteDisplayInfo", "IGuest"); | |
53 AddInterfaceTypes("IVirtualSystemDescription", "IAudioAdapter", "IExtPackManager", "IVRDEServer"); | |
54 AddInterfaceTypes("IPciDeviceAttachment", "IBandwidthGroup"); | |
55 | |
56 AddEnumTypes("LockType", "MediumVariant", "AccessMode", "NATProtocol", "FirmwareType", "StorageControllerType"); | |
57 AddEnumTypes("StorageBus", "SessionType", "SessionState", "USBDeviceState", "USBDeviceFilterAction", "Scope"); | |
58 AddEnumTypes("AudioControllerType", "AudioDriverType", "VRDPAuthType", "MachineState", "NetworkAdapterType"); | |
59 AddEnumTypes("NetworkAttachmentType", "PortMode", "DeviceType", "MediumState", "VFSType", "MediumType"); | |
60 AddEnumTypes("HostNetworkInterfaceType", "DeviceActivity", "HostNetworkInterfaceMediumType", "HostNetworkInterfaceStatus"); | |
61 AddEnumTypes("ProcessorFeature", "BIOSBootMenuMode", "VirtualSystemDescriptionType", "VirtualSystemDescriptionValueType"); | |
62 AddEnumTypes("KeyboardHidType", "ClipboardMode", "PointingHidType", "CPUPropertyType", "HWVirtExPropertyType"); | |
63 AddEnumTypes("ChipsetType", "FaultToleranceState", "BandwidthGroupType", "ExecuteProcessStatus", "VBoxEventType"); | |
64 AddEnumTypes("GuestMonitorChangedEventType", "AuthType", "NetworkAdapterPromiscModePolicy", "AdditionsRunLevelType"); | |
65 AddEnumTypes("AdditionsFacilityStatus", "AdditionsFacilityType", "AdditionsFacilityClass", "CleanupMode", "DataType"); | |
66 } | |
67 | |
68 public XidlParser() { | |
69 Library = new LibraryInfo(); | |
70 UnknownType = new ValueTypeInfo("IntPtr"); | |
71 Library.Interfaces.Add("IUnknown", new InterfaceInfo("IUnknown", new Guid("00000000-0000-0000-C000-000000000046"))); | |
72 Library.Interfaces.Add("IErrorInfo", new InterfaceInfo("IErrorInfo", new Guid("00000000-0000-0000-C000-000000000046"), Library.Interfaces["IUnknown"])); | |
73 Library.Interfaces.Add("IDispatch", new InterfaceInfo("IDispatch", new Guid("00020400-0000-0000-C000-000000000046"), Library.Interfaces["IUnknown"])); | |
74 BaseInterfaceType = Library.Interfaces["IUnknown"]; | |
75 ErrorInterfaceType = Library.Interfaces["IErrorInfo"]; | |
76 InitTypes(); | |
77 } | |
78 | |
79 public void Parse(XPathNavigator nav) { | |
80 //XPathDocument doc = new XPathDocument("VirtualBox.xidl"); | |
81 //XPathNavigator nav = doc.CreateNavigator(); | |
82 nav = nav.SelectSingleNode("/idl/library"); //[@name='VirtualBox'] | |
83 foreach (XPathNavigator intf in nav.Select("interface")) { | |
84 ProcessInterface(intf, nav); | |
85 } | |
86 foreach (XPathNavigator intf in nav.Select("enum")) { | |
87 ProcessEnum(intf); | |
88 } | |
89 } | |
90 void ProcessEnum(XPathNavigator nav) { | |
91 String typeName = nav.SelectSingleNode("@name").Value; | |
92 EnumInfo typeInfo = new EnumInfo(typeName); | |
93 foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { | |
94 switch (member.Name) { | |
95 case "desc": break; | |
96 case "const": { | |
97 String numberString = member.SelectSingleNode("@value").Value; | |
98 Int32 number = 0; | |
99 if (numberString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) { | |
100 number = Int32.Parse(numberString.Substring(2), System.Globalization.NumberStyles.HexNumber); | |
101 } else { | |
102 number = Int32.Parse(numberString); | |
103 } | |
104 typeInfo.Values.Add(member.SelectSingleNode("@name").Value, number); | |
105 } break; | |
106 default: | |
107 Console.Error.WriteLine("Unknown member type {0}", member.Name); | |
108 break; | |
109 } | |
110 } | |
111 Library.Enums.Add(typeName, typeInfo); | |
112 } | |
113 void ProcessInterface(XPathNavigator nav, XPathNavigator parentNav) { | |
114 String typeName = nav.SelectSingleNode("@name").Value; | |
115 String typeIid = nav.SelectSingleNode("@uuid").Value; | |
116 XPathItem item = nav.SelectSingleNode("@extends"); | |
117 InterfaceInfo typeExtends = null; | |
118 if (item != null) { | |
119 switch (item.Value) { | |
120 case "$unknown": typeExtends = BaseInterfaceType; break; | |
121 case "$errorinfo": typeExtends = ErrorInterfaceType; break; | |
122 default: typeExtends = Library.Interfaces[item.Value]; break; | |
123 } | |
124 } | |
125 InterfaceInfo typeInfo = new InterfaceInfo(typeName, new Guid(typeIid), typeExtends); | |
126 foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { | |
127 switch (member.Name) { | |
128 case "desc": break; | |
129 case "attribute": { | |
130 String mName = member.SelectSingleNode("@name").Value; | |
131 item = member.SelectSingleNode("@readonly"); | |
132 Boolean mReadOnly = item == null ? false : item.Value == "yes"; | |
133 item = member.SelectSingleNode("@writeonly"); | |
134 Boolean mWriteOnly = item == null ? false : item.Value == "yes"; | |
135 mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); | |
136 PropertyInfo mInfo = new PropertyInfo(mName, GetTypeDeclaration(member), !mWriteOnly, !mReadOnly); | |
137 typeInfo.Members.Add(mInfo); | |
138 } break; | |
139 case "method": { | |
140 String mName = member.SelectSingleNode("@name").Value; | |
141 XPathNodeIterator mParamReturn = member.Select("param[@dir='return']"); | |
142 bool mReturn = false; | |
143 TypeInfo mReturnType = null; | |
144 if (mParamReturn == null || mParamReturn.Count != 1) { | |
145 } else { | |
146 mParamReturn.MoveNext(); | |
147 mReturn = true; | |
148 mReturnType = GetTypeDeclaration(mParamReturn.Current); | |
149 } | |
150 mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); | |
151 MethodInfo mInfo = new MethodInfo(mName, mReturnType); | |
152 foreach (XPathNavigator mParam in member.Select("param")) { | |
153 String pDir = mParam.SelectSingleNode("@dir").Value; | |
154 if (pDir == "return" && mReturn) continue; | |
155 ParameterType pt = pDir == "out" ? ParameterType.Out : ParameterType.In; | |
156 TypeInfo mType = GetTypeDeclaration(mParam, ref pt); | |
157 mInfo.Parameters.Add(new MethodParameterInfo(mParam.SelectSingleNode("@name").Value, mType, pDir != "out", pt == ParameterType.Reference, pDir == "out")); | |
158 } | |
159 typeInfo.Members.Add(mInfo); | |
160 } break; | |
161 default: | |
162 Console.Error.WriteLine("Unknown member type {0}", member.Name); | |
163 break; | |
164 } | |
165 } | |
166 Library.Interfaces.Add(typeName, typeInfo); | |
167 } | |
168 private TypeInfo GetTypeDeclaration(XPathNavigator nav) { | |
169 ParameterType paramType = ParameterType.Param; | |
170 return GetTypeDeclaration(nav, ref paramType); | |
171 } | |
172 private TypeInfo GetTypeDeclaration(XPathNavigator nav, ref ParameterType paramType) { | |
173 String mType = nav.SelectSingleNode("@type").Value; | |
174 XPathItem item; | |
175 item = nav.SelectSingleNode("@mod"); | |
176 String mMod = item == null ? null : item.Value; | |
177 item = nav.SelectSingleNode("@safearray"); | |
178 Boolean pArray = item == null ? false : item.Value == "yes"; | |
179 | |
180 TypeInfo t; | |
181 if (!Types.TryGetValue(mType, out t)) { | |
182 t = null; | |
183 } | |
184 if (mMod == "ptr") { | |
185 if (paramType == ParameterType.In) { | |
186 paramType = ParameterType.Reference; | |
187 } else { | |
188 t = new ValueTypeInfo(typeof(IntPtr)); | |
189 } | |
190 } else if (mMod == "string") { | |
191 t = Types["wstring"]; | |
192 } else if (mMod != null) { | |
193 Console.Error.WriteLine("Type modifier {0} is not supported", mMod); | |
194 t = UnknownType; | |
195 } | |
196 if (t == null) { | |
197 Console.Error.WriteLine("Type {0} is not supported", mType); | |
198 t = UnknownType; | |
199 } | |
200 if (pArray) { | |
201 Console.Error.WriteLine("Array type not supported"); | |
202 t = null; | |
203 t = UnknownType; | |
204 } | |
205 return t; | |
206 } | |
207 } | |
208 } |