Ivo@0: //+reference System.dll Ivo@0: //+reference System.Xml.dll Ivo@0: using System; Ivo@0: using System.Xml.XPath; Ivo@0: using System.IO; Ivo@0: using System.Collections.Generic; Ivo@0: class Program { Ivo@0: enum ParameterType { Ivo@0: In, Ivo@0: Out, Ivo@0: Reference, Ivo@0: Return, Ivo@0: Param, Ivo@0: } Ivo@0: class TypeInfo { Ivo@0: public String Name { get; private set; } Ivo@0: public String[] Attributes { get; private set; } Ivo@0: Ivo@0: public TypeInfo(String name, params String[] attributes) { Ivo@0: this.Name = name; Ivo@0: this.Attributes = attributes; Ivo@0: } Ivo@0: public void WriteDeclaration(TextWriter o, ParameterType vartype) { Ivo@0: WriteAttributes(o, vartype); Ivo@0: o.Write(Name); Ivo@0: } Ivo@0: public void WriteAttributes(TextWriter o, ParameterType vartype) { Ivo@0: foreach (String attribute in Attributes) { Ivo@0: o.Write("["); Ivo@0: if (vartype == ParameterType.Return) o.Write("return: "); Ivo@0: else if (vartype == ParameterType.Param) o.Write("param: "); Ivo@0: o.Write(attribute); Ivo@0: o.Write("] "); Ivo@0: } Ivo@0: if (vartype == ParameterType.Out) o.Write("out "); Ivo@0: else if (vartype == ParameterType.Reference) o.Write("ref "); Ivo@0: } Ivo@0: } Ivo@0: static Dictionary Types = new Dictionary(); Ivo@2: static void AddInterfaceTypes(params String[] names) { Ivo@2: foreach (String name in names) Types.Add(name, new TypeInfo(name, "MarshalAs(UnmanagedType.Interface)")); Ivo@2: } Ivo@2: static void AddEnumTypes(params String[] names) { Ivo@2: foreach (String name in names) Types.Add(name, new TypeInfo(name)); Ivo@2: } Ivo@0: static void InitTypes() { Ivo@0: Types.Add("short", new TypeInfo("Int16")); Ivo@0: Types.Add("unsigned short", new TypeInfo("UInt16")); Ivo@0: Types.Add("unsigned long", new TypeInfo("UInt32")); Ivo@0: Types.Add("long long", new TypeInfo("Int64")); Ivo@0: Types.Add("long", new TypeInfo("Int32")); Ivo@0: Types.Add("octet", new TypeInfo("Byte")); Ivo@0: Types.Add("unsigned long long", new TypeInfo("UInt32")); Ivo@0: //Types.Add("boolean", new TypeInfo("Boolean", "MarshalAs(UnmanagedType.Bool)")); Ivo@0: Types.Add("boolean", new TypeInfo("Int32")); Ivo@0: Types.Add("wstring", new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)")); Ivo@0: //Types.Add("uuid", new TypeInfo("Guid", true, "MarshalAs(UnmanagedType.LPStruct)")); Ivo@0: Types.Add("uuid", new TypeInfo("Guid", "MarshalAs(UnmanagedType.LPStruct)")); Ivo@2: Types.Add("$unknown", new TypeInfo("IntPtr")); Ivo@0: Ivo@2: AddInterfaceTypes("IMachine", "ISession", "IVirtualBox", "IHost", "IConsole", "ISystemProperties"); Ivo@2: AddInterfaceTypes("IProgress", "IDisplay", "IMouse", "IKeyboard", "IFramebuffer", "IFramebufferOverlay"); Ivo@2: AddInterfaceTypes("IMachineDebugger", "IVirtualBoxErrorInfo", "IEventSource", "IEventListener", "IEventContext"); Ivo@2: AddInterfaceTypes("IConsoleCallback", "IEvent", "IBandwidthControl", "IVRDEServerInfo", "IAdditionsFacility"); Ivo@2: AddInterfaceTypes("IExtPackPlugIn", "IExtPackFile", "IExtPack", "IBIOSSettings", "IVFSExplorer", "IUSBController"); Ivo@2: AddInterfaceTypes("IStorageController", "IVRDPServer", "ISnapshot", "INATEngine", "IUSBDeviceFilter"); Ivo@2: AddInterfaceTypes("IMediumAttachment", "IUSBDevice", "IParallelPort", "ISerialPort", "INetworkAdapter"); Ivo@2: AddInterfaceTypes("IMedium", "IGuestOSType", "ISharedFolder", "IPerformanceCollector", "IDHCPServer"); Ivo@2: AddInterfaceTypes("IAppliance", "IVirtualBoxCallback", "IPerformanceMetric", "IMediumFormat", "IHostUSBDevice"); Ivo@2: AddInterfaceTypes("IHostNetworkInterface", "IHostUSBDeviceFilter", "IRemoteDisplayInfo", "IGuest"); Ivo@2: AddInterfaceTypes("IVirtualSystemDescription", "IAudioAdapter", "IExtPackManager", "IVRDEServer"); Ivo@2: AddInterfaceTypes("IPciDeviceAttachment", "IBandwidthGroup"); Ivo@2: Ivo@2: AddEnumTypes("LockType", "MediumVariant", "AccessMode", "NATProtocol", "FirmwareType", "StorageControllerType"); Ivo@2: AddEnumTypes("StorageBus", "SessionType", "SessionState", "USBDeviceState", "USBDeviceFilterAction"); Ivo@2: AddEnumTypes("AudioControllerType", "AudioDriverType", "VRDPAuthType", "MachineState", "NetworkAdapterType"); Ivo@2: AddEnumTypes("NetworkAttachmentType", "PortMode", "DeviceType", "MediumState", "VFSType", "MediumType"); Ivo@2: AddEnumTypes("HostNetworkInterfaceType", "DeviceActivity", "HostNetworkInterfaceMediumType", "HostNetworkInterfaceStatus"); Ivo@2: AddEnumTypes("ProcessorFeature", "BIOSBootMenuMode", "VirtualSystemDescriptionType", "VirtualSystemDescriptionValueType"); Ivo@2: AddEnumTypes("KeyboardHidType", "ClipboardMode", "PointingHidType", "CPUPropertyType", "HWVirtExPropertyType"); Ivo@2: AddEnumTypes("ChipsetType", "FaultToleranceState", "BandwidthGroupType", "ExecuteProcessStatus", "VBoxEventType"); Ivo@2: AddEnumTypes("GuestMonitorChangedEventType", "AuthType", "NetworkAdapterPromiscModePolicy", "AdditionsRunLevelType"); Ivo@2: AddEnumTypes("AdditionsFacilityStatus", "AdditionsFacilityType", "AdditionsFacilityClass", "CleanupMode", "DataType"); Ivo@0: } Ivo@0: static void Main(string[] args) { Ivo@0: InitTypes(); Ivo@0: Ivo@0: XPathDocument doc = new XPathDocument("VirtualBox.xidl"); Ivo@0: XPathNavigator nav = doc.CreateNavigator(); Ivo@0: nav = nav.SelectSingleNode("/idl/library[@name='VirtualBox']"); Ivo@0: TextWriter o = Console.Out; Ivo@0: o.WriteLine("using System;"); Ivo@0: o.WriteLine("using System.Runtime.CompilerServices;"); Ivo@0: o.WriteLine("using System.Runtime.InteropServices;"); Ivo@0: o.WriteLine("namespace VirtualBox {"); Ivo@0: foreach (XPathNavigator intf in nav.Select("interface")) { Ivo@0: ProcessInterface(intf, o, nav); Ivo@0: } Ivo@0: foreach (XPathNavigator intf in nav.Select("enum")) { Ivo@0: ProcessEnum(intf, o); Ivo@0: } Ivo@0: o.WriteLine("}"); Ivo@0: } Ivo@0: static void ProcessEnum(XPathNavigator nav, TextWriter o) { Ivo@0: String typeName = nav.SelectSingleNode("@name").Value; Ivo@0: if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName)); Ivo@0: o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value); Ivo@0: o.WriteLine("enum " + typeName + " {"); Ivo@0: foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { Ivo@0: switch (member.Name) { Ivo@0: case "desc": Ivo@0: break; Ivo@0: case "const": Ivo@0: o.WriteLine("\t{0} = {1},", member.SelectSingleNode("@name").Value, member.SelectSingleNode("@value").Value); Ivo@0: break; Ivo@0: default: Ivo@0: Console.Error.WriteLine("Unknown member type {0}", member.Name); Ivo@0: break; Ivo@0: } Ivo@0: } Ivo@0: o.WriteLine("}"); Ivo@0: } Ivo@0: static void ProcessInterface(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) { Ivo@0: String typeName = nav.SelectSingleNode("@name").Value; Ivo@0: if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName, "MarshalAs(UnmanagedType.Interface)")); Ivo@0: o.WriteLine("[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]"); Ivo@0: o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value); Ivo@0: o.WriteLine("[ComImport()]"); Ivo@0: o.Write("interface " + typeName); Ivo@0: o.WriteLine(" {"); Ivo@0: ProcessInterfaceMembersAndInherited(nav, o, parentNav); Ivo@0: o.WriteLine("}"); Ivo@0: } Ivo@0: static void ProcessInterfaceMembersAndInherited(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) { Ivo@0: XPathItem item = nav.SelectSingleNode("@extends"); Ivo@0: if (item != null && item.Value[0] != '$') { Ivo@0: XPathNavigator inav = parentNav.SelectSingleNode("interface[@name='" + item.Value + "']"); Ivo@0: ProcessInterfaceMembersAndInherited(inav, o, parentNav); Ivo@0: } Ivo@0: ProcessInterfaceMembers(nav.SelectChildren(XPathNodeType.Element), o); Ivo@0: } Ivo@0: static void ProcessInterfaceMembers(XPathNodeIterator members, TextWriter oattribute) { Ivo@0: XPathItem item; Ivo@0: StringWriter omethod = new StringWriter(); Ivo@0: foreach (XPathNavigator member in members) { Ivo@0: switch (member.Name) { Ivo@0: case "desc": Ivo@0: break; Ivo@0: case "attribute": { Ivo@0: String mName = member.SelectSingleNode("@name").Value; Ivo@0: item = member.SelectSingleNode("@readonly"); Ivo@0: Boolean mReadOnly = item == null ? false : item.Value == "yes"; Ivo@0: mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); Ivo@0: oattribute.Write("\t"); Ivo@0: TypeInfo t = GetTypeDeclaration(member); Ivo@0: oattribute.Write(t.Name); Ivo@0: oattribute.Write(" "); Ivo@0: oattribute.Write(mName); Ivo@0: oattribute.WriteLine(" {"); Ivo@0: oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] "); Ivo@0: t.WriteAttributes(oattribute, ParameterType.Return); Ivo@0: oattribute.WriteLine("get;"); Ivo@0: if (!mReadOnly) { Ivo@0: oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] "); Ivo@0: t.WriteAttributes(oattribute, ParameterType.Param); Ivo@0: oattribute.WriteLine("set;"); Ivo@0: } Ivo@0: oattribute.WriteLine("\t}"); Ivo@0: } break; Ivo@0: case "method": { Ivo@0: String mName = member.SelectSingleNode("@name").Value; Ivo@0: XPathNodeIterator mParamReturn = member.Select("param[@dir='return']"); Ivo@0: omethod.WriteLine("\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]"); Ivo@0: omethod.Write("\t"); Ivo@0: bool mReturn = false; Ivo@0: if (mParamReturn == null || mParamReturn.Count != 1) { Ivo@0: omethod.Write("void"); Ivo@0: } else { Ivo@0: mParamReturn.MoveNext(); Ivo@0: mReturn = true; Ivo@2: WriteTypeDeclaration(omethod, mParamReturn.Current, ParameterType.Return); Ivo@0: } Ivo@0: mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); Ivo@0: omethod.Write(" "); Ivo@0: omethod.Write(mName); Ivo@0: omethod.Write("("); Ivo@0: XPathNodeIterator mParams = member.Select("param"); Ivo@0: bool first = true; Ivo@0: if (mParams.MoveNext()) { Ivo@0: while (true) { Ivo@0: XPathNavigator mParam = mParams.Current; Ivo@0: String pDir = mParam.SelectSingleNode("@dir").Value; Ivo@0: if (pDir == "return" && mReturn) { Ivo@0: if (mParams.MoveNext()) { Ivo@0: continue; Ivo@0: } else { Ivo@0: break; Ivo@0: } Ivo@0: } else if (pDir == "in") { Ivo@0: } else if (pDir == "out") { Ivo@0: } else { Ivo@0: Console.Error.WriteLine("Unsupported parameter direction {0}", pDir); Ivo@0: } Ivo@0: if (first) { Ivo@0: first = false; Ivo@0: } else { Ivo@0: omethod.Write(", "); Ivo@0: } Ivo@2: WriteTypeDeclaration(omethod, mParam, pDir == "out" ? ParameterType.Out : ParameterType.In); Ivo@0: omethod.Write(" p"); Ivo@0: omethod.Write(mParam.SelectSingleNode("@name").Value); Ivo@0: if (!mParams.MoveNext()) break; Ivo@0: } Ivo@0: } Ivo@0: omethod.WriteLine(");"); Ivo@0: } break; Ivo@0: default: Ivo@0: Console.Error.WriteLine("Unknown member type {0}", member.Name); Ivo@0: break; Ivo@0: } Ivo@0: } Ivo@0: oattribute.Write((omethod as StringWriter).ToString()); Ivo@0: } Ivo@0: private static TypeInfo GetTypeDeclaration(XPathNavigator nav) { Ivo@0: ParameterType pt = ParameterType.Param; Ivo@0: return GetTypeDeclaration(nav, ref pt); Ivo@0: } Ivo@2: private static void WriteTypeDeclaration(TextWriter o, XPathNavigator nav, ParameterType paramType) { Ivo@2: TypeInfo t = GetTypeDeclaration(nav, ref paramType); Ivo@2: t.WriteDeclaration(o, paramType); Ivo@2: } Ivo@0: private static TypeInfo GetTypeDeclaration(XPathNavigator nav, ref ParameterType paramType) { Ivo@0: String mType = nav.SelectSingleNode("@type").Value; Ivo@0: XPathItem item; Ivo@0: item = nav.SelectSingleNode("@mod"); Ivo@0: String mMod = item == null ? null : item.Value; Ivo@0: item = nav.SelectSingleNode("@safearray"); Ivo@0: Boolean pArray = item == null ? false : item.Value == "yes"; Ivo@0: Ivo@0: TypeInfo t; Ivo@0: if (!Types.TryGetValue(mType, out t)) { Ivo@0: Console.Error.WriteLine("Type {0} is not supported", mType); Ivo@0: t = new TypeInfo("void"); Ivo@0: } Ivo@0: if (mMod == "ptr") { Ivo@0: if (paramType == ParameterType.In) { Ivo@0: paramType = ParameterType.Reference; Ivo@0: } else { Ivo@0: t = new TypeInfo("IntPtr"); Ivo@0: } Ivo@0: } else if (mMod == "string") { Ivo@0: t = new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)"); Ivo@0: } else if (mMod != null) { Ivo@0: Console.Error.WriteLine("Type modifier {0} is not supported", mMod); Ivo@0: t = new TypeInfo("void"); Ivo@0: } Ivo@0: if (pArray) { Ivo@0: t = new TypeInfo("Array", "MarshalAs(UnmanagedType.SafeArray)"); Ivo@0: if (paramType == ParameterType.In || paramType == ParameterType.Out) paramType = ParameterType.Reference; Ivo@0: } Ivo@0: return t; Ivo@0: } Ivo@0: }