Mercurial > hg > vboxdotnet
view InteropCodeGen/XidlParser.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 |
line wrap: on
line source
using System; using System.Xml.XPath; using System.IO; using System.Collections.Generic; namespace VBoxSDK { public class XidlParser { public LibraryInfo Library { get; private set; } public TypeInfo UnknownType { get; set; } public InterfaceInfo BaseInterfaceType { get; set; } public InterfaceInfo ErrorInterfaceType { get; set; } enum ParameterType { In, Out, Reference, Return, Param, } public Dictionary<String, TypeInfo> Types = new Dictionary<string, TypeInfo>(); void AddInterfaceTypes(params String[] names) { foreach (String name in names) Types.Add(name, new InterfaceTypeInfo(name)); } void AddEnumTypes(params String[] names) { foreach (String name in names) Types.Add(name, new ValueTypeInfo(name)); } void InitTypes() { Types.Add("short", new ValueTypeInfo(typeof(Int32))); Types.Add("unsigned short", new ValueTypeInfo(typeof(UInt16))); Types.Add("unsigned long", new ValueTypeInfo(typeof(UInt32))); Types.Add("long long", new ValueTypeInfo(typeof(Int64))); Types.Add("long", new ValueTypeInfo(typeof(Int32))); Types.Add("octet", new ValueTypeInfo(typeof(Byte))); Types.Add("unsigned long long", new ValueTypeInfo(typeof(UInt32))); //Types.Add("boolean", new TypeInfo("Boolean", "MarshalAs(UnmanagedType.Bool)")); Types.Add("boolean", new ValueTypeInfo(typeof(Int32))); //Types.Add("wstring", new ValueTypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)")); //Types.Add("uuid", new TypeInfo("Guid", true, "MarshalAs(UnmanagedType.LPStruct)")); //Types.Add("uuid", new ValueTypeInfo("Guid", "MarshalAs(UnmanagedType.LPStruct)")); Types.Add("wstring", new StringTypeInfo()); Types.Add("$unknown", new ValueTypeInfo(typeof(IntPtr))); AddInterfaceTypes("IMachine", "ISession", "IVirtualBox", "IHost", "IConsole", "ISystemProperties"); AddInterfaceTypes("IProgress", "IDisplay", "IMouse", "IKeyboard", "IFramebuffer", "IFramebufferOverlay"); AddInterfaceTypes("IMachineDebugger", "IVirtualBoxErrorInfo", "IEventSource", "IEventListener", "IEventContext"); AddInterfaceTypes("IConsoleCallback", "IEvent", "IBandwidthControl", "IVRDEServerInfo", "IAdditionsFacility"); AddInterfaceTypes("IExtPackPlugIn", "IExtPackFile", "IExtPack", "IBIOSSettings", "IVFSExplorer", "IUSBController"); AddInterfaceTypes("IStorageController", "IVRDPServer", "ISnapshot", "INATEngine", "IUSBDeviceFilter"); AddInterfaceTypes("IMediumAttachment", "IUSBDevice", "IParallelPort", "ISerialPort", "INetworkAdapter"); AddInterfaceTypes("IMedium", "IGuestOSType", "ISharedFolder", "IPerformanceCollector", "IDHCPServer"); AddInterfaceTypes("IAppliance", "IVirtualBoxCallback", "IPerformanceMetric", "IMediumFormat", "IHostUSBDevice"); AddInterfaceTypes("IHostNetworkInterface", "IHostUSBDeviceFilter", "IRemoteDisplayInfo", "IGuest"); AddInterfaceTypes("IVirtualSystemDescription", "IAudioAdapter", "IExtPackManager", "IVRDEServer"); AddInterfaceTypes("IPciDeviceAttachment", "IBandwidthGroup"); AddEnumTypes("LockType", "MediumVariant", "AccessMode", "NATProtocol", "FirmwareType", "StorageControllerType"); AddEnumTypes("StorageBus", "SessionType", "SessionState", "USBDeviceState", "USBDeviceFilterAction", "Scope"); AddEnumTypes("AudioControllerType", "AudioDriverType", "VRDPAuthType", "MachineState", "NetworkAdapterType"); AddEnumTypes("NetworkAttachmentType", "PortMode", "DeviceType", "MediumState", "VFSType", "MediumType"); AddEnumTypes("HostNetworkInterfaceType", "DeviceActivity", "HostNetworkInterfaceMediumType", "HostNetworkInterfaceStatus"); AddEnumTypes("ProcessorFeature", "BIOSBootMenuMode", "VirtualSystemDescriptionType", "VirtualSystemDescriptionValueType"); AddEnumTypes("KeyboardHidType", "ClipboardMode", "PointingHidType", "CPUPropertyType", "HWVirtExPropertyType"); AddEnumTypes("ChipsetType", "FaultToleranceState", "BandwidthGroupType", "ExecuteProcessStatus", "VBoxEventType"); AddEnumTypes("GuestMonitorChangedEventType", "AuthType", "NetworkAdapterPromiscModePolicy", "AdditionsRunLevelType"); AddEnumTypes("AdditionsFacilityStatus", "AdditionsFacilityType", "AdditionsFacilityClass", "CleanupMode", "DataType"); } public XidlParser() { Library = new LibraryInfo(); UnknownType = new ValueTypeInfo("IntPtr"); Library.Interfaces.Add("IUnknown", new InterfaceInfo("IUnknown", new Guid("00000000-0000-0000-C000-000000000046"))); Library.Interfaces.Add("IErrorInfo", new InterfaceInfo("IErrorInfo", new Guid("00000000-0000-0000-C000-000000000046"), Library.Interfaces["IUnknown"])); Library.Interfaces.Add("IDispatch", new InterfaceInfo("IDispatch", new Guid("00020400-0000-0000-C000-000000000046"), Library.Interfaces["IUnknown"])); BaseInterfaceType = Library.Interfaces["IUnknown"]; ErrorInterfaceType = Library.Interfaces["IErrorInfo"]; InitTypes(); } public void Parse(XPathNavigator nav) { //XPathDocument doc = new XPathDocument("VirtualBox.xidl"); //XPathNavigator nav = doc.CreateNavigator(); nav = nav.SelectSingleNode("/idl/library"); //[@name='VirtualBox'] foreach (XPathNavigator intf in nav.Select("interface")) { ProcessInterface(intf, nav); } foreach (XPathNavigator intf in nav.Select("enum")) { ProcessEnum(intf); } } void ProcessEnum(XPathNavigator nav) { String typeName = nav.SelectSingleNode("@name").Value; EnumInfo typeInfo = new EnumInfo(typeName); foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { switch (member.Name) { case "desc": break; case "const": { String numberString = member.SelectSingleNode("@value").Value; Int32 number = 0; if (numberString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) { number = Int32.Parse(numberString.Substring(2), System.Globalization.NumberStyles.HexNumber); } else { number = Int32.Parse(numberString); } typeInfo.Values.Add(member.SelectSingleNode("@name").Value, number); } break; default: Console.Error.WriteLine("Unknown member type {0}", member.Name); break; } } Library.Enums.Add(typeName, typeInfo); } void ProcessInterface(XPathNavigator nav, XPathNavigator parentNav) { String typeName = nav.SelectSingleNode("@name").Value; String typeIid = nav.SelectSingleNode("@uuid").Value; XPathItem item = nav.SelectSingleNode("@extends"); InterfaceInfo typeExtends = null; if (item != null) { switch (item.Value) { case "$unknown": typeExtends = BaseInterfaceType; break; case "$errorinfo": typeExtends = ErrorInterfaceType; break; default: typeExtends = Library.Interfaces[item.Value]; break; } } InterfaceInfo typeInfo = new InterfaceInfo(typeName, new Guid(typeIid), typeExtends); foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { switch (member.Name) { case "desc": break; case "attribute": { String mName = member.SelectSingleNode("@name").Value; item = member.SelectSingleNode("@readonly"); Boolean mReadOnly = item == null ? false : item.Value == "yes"; item = member.SelectSingleNode("@writeonly"); Boolean mWriteOnly = item == null ? false : item.Value == "yes"; mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); PropertyInfo mInfo = new PropertyInfo(mName, GetTypeDeclaration(member), !mWriteOnly, !mReadOnly); typeInfo.Members.Add(mInfo); } break; case "method": { String mName = member.SelectSingleNode("@name").Value; XPathNodeIterator mParamReturn = member.Select("param[@dir='return']"); bool mReturn = false; TypeInfo mReturnType = null; if (mParamReturn == null || mParamReturn.Count != 1) { } else { mParamReturn.MoveNext(); mReturn = true; mReturnType = GetTypeDeclaration(mParamReturn.Current); } mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); MethodInfo mInfo = new MethodInfo(mName, mReturnType); foreach (XPathNavigator mParam in member.Select("param")) { String pDir = mParam.SelectSingleNode("@dir").Value; if (pDir == "return" && mReturn) continue; ParameterType pt = pDir == "out" ? ParameterType.Out : ParameterType.In; TypeInfo mType = GetTypeDeclaration(mParam, ref pt); mInfo.Parameters.Add(new MethodParameterInfo(mParam.SelectSingleNode("@name").Value, mType, pDir != "out", pt == ParameterType.Reference, pDir == "out")); } typeInfo.Members.Add(mInfo); } break; default: Console.Error.WriteLine("Unknown member type {0}", member.Name); break; } } Library.Interfaces.Add(typeName, typeInfo); } private TypeInfo GetTypeDeclaration(XPathNavigator nav) { ParameterType paramType = ParameterType.Param; return GetTypeDeclaration(nav, ref paramType); } private TypeInfo GetTypeDeclaration(XPathNavigator nav, ref ParameterType paramType) { String mType = nav.SelectSingleNode("@type").Value; XPathItem item; item = nav.SelectSingleNode("@mod"); String mMod = item == null ? null : item.Value; item = nav.SelectSingleNode("@safearray"); Boolean pArray = item == null ? false : item.Value == "yes"; TypeInfo t; if (!Types.TryGetValue(mType, out t)) { t = null; } if (mMod == "ptr") { if (paramType == ParameterType.In) { paramType = ParameterType.Reference; } else { t = new ValueTypeInfo(typeof(IntPtr)); } } else if (mMod == "string") { t = Types["wstring"]; } else if (mMod != null) { Console.Error.WriteLine("Type modifier {0} is not supported", mMod); t = UnknownType; } if (t == null) { Console.Error.WriteLine("Type {0} is not supported", mType); t = UnknownType; } if (pArray) { Console.Error.WriteLine("Array type not supported"); t = null; t = UnknownType; } return t; } } }