Mercurial > hg > vboxdotnet
view InteropCodeGen/gendotnet.cs @ 2:f1deea9c97a0
Cleaned up the interop code generator, added wrapper application to initialize kernel driver and run mono
author | Ivo Smits |
---|---|
date | Wed, 04 May 2011 16:10:08 +0200 |
parents | e1ec7bf71313 |
children | 64226294e26b |
line wrap: on
line source
//+reference System.dll //+reference System.Xml.dll using System; using System.Xml.XPath; using System.IO; using System.Collections.Generic; class Program { enum ParameterType { In, Out, Reference, Return, Param, } class TypeInfo { public String Name { get; private set; } public String[] Attributes { get; private set; } public TypeInfo(String name, params String[] attributes) { this.Name = name; this.Attributes = attributes; } public void WriteDeclaration(TextWriter o, ParameterType vartype) { WriteAttributes(o, vartype); o.Write(Name); } public void WriteAttributes(TextWriter o, ParameterType vartype) { foreach (String attribute in Attributes) { o.Write("["); if (vartype == ParameterType.Return) o.Write("return: "); else if (vartype == ParameterType.Param) o.Write("param: "); o.Write(attribute); o.Write("] "); } if (vartype == ParameterType.Out) o.Write("out "); else if (vartype == ParameterType.Reference) o.Write("ref "); } } static Dictionary<String, TypeInfo> Types = new Dictionary<string, TypeInfo>(); static void AddInterfaceTypes(params String[] names) { foreach (String name in names) Types.Add(name, new TypeInfo(name, "MarshalAs(UnmanagedType.Interface)")); } static void AddEnumTypes(params String[] names) { foreach (String name in names) Types.Add(name, new TypeInfo(name)); } static void InitTypes() { Types.Add("short", new TypeInfo("Int16")); Types.Add("unsigned short", new TypeInfo("UInt16")); Types.Add("unsigned long", new TypeInfo("UInt32")); Types.Add("long long", new TypeInfo("Int64")); Types.Add("long", new TypeInfo("Int32")); Types.Add("octet", new TypeInfo("Byte")); Types.Add("unsigned long long", new TypeInfo("UInt32")); //Types.Add("boolean", new TypeInfo("Boolean", "MarshalAs(UnmanagedType.Bool)")); Types.Add("boolean", new TypeInfo("Int32")); Types.Add("wstring", new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)")); //Types.Add("uuid", new TypeInfo("Guid", true, "MarshalAs(UnmanagedType.LPStruct)")); Types.Add("uuid", new TypeInfo("Guid", "MarshalAs(UnmanagedType.LPStruct)")); Types.Add("$unknown", new TypeInfo("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"); 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"); } static void Main(string[] args) { InitTypes(); XPathDocument doc = new XPathDocument("VirtualBox.xidl"); XPathNavigator nav = doc.CreateNavigator(); nav = nav.SelectSingleNode("/idl/library[@name='VirtualBox']"); TextWriter o = Console.Out; o.WriteLine("using System;"); o.WriteLine("using System.Runtime.CompilerServices;"); o.WriteLine("using System.Runtime.InteropServices;"); o.WriteLine("namespace VirtualBox {"); foreach (XPathNavigator intf in nav.Select("interface")) { ProcessInterface(intf, o, nav); } foreach (XPathNavigator intf in nav.Select("enum")) { ProcessEnum(intf, o); } o.WriteLine("}"); } static void ProcessEnum(XPathNavigator nav, TextWriter o) { String typeName = nav.SelectSingleNode("@name").Value; if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName)); o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value); o.WriteLine("enum " + typeName + " {"); foreach (XPathNavigator member in nav.SelectChildren(XPathNodeType.Element)) { switch (member.Name) { case "desc": break; case "const": o.WriteLine("\t{0} = {1},", member.SelectSingleNode("@name").Value, member.SelectSingleNode("@value").Value); break; default: Console.Error.WriteLine("Unknown member type {0}", member.Name); break; } } o.WriteLine("}"); } static void ProcessInterface(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) { String typeName = nav.SelectSingleNode("@name").Value; if (!Types.ContainsKey(typeName)) Types.Add(typeName, new TypeInfo(typeName, "MarshalAs(UnmanagedType.Interface)")); o.WriteLine("[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]"); o.WriteLine("[Guid(\"{0}\")]", nav.SelectSingleNode("@uuid").Value); o.WriteLine("[ComImport()]"); o.Write("interface " + typeName); o.WriteLine(" {"); ProcessInterfaceMembersAndInherited(nav, o, parentNav); o.WriteLine("}"); } static void ProcessInterfaceMembersAndInherited(XPathNavigator nav, TextWriter o, XPathNavigator parentNav) { XPathItem item = nav.SelectSingleNode("@extends"); if (item != null && item.Value[0] != '$') { XPathNavigator inav = parentNav.SelectSingleNode("interface[@name='" + item.Value + "']"); ProcessInterfaceMembersAndInherited(inav, o, parentNav); } ProcessInterfaceMembers(nav.SelectChildren(XPathNodeType.Element), o); } static void ProcessInterfaceMembers(XPathNodeIterator members, TextWriter oattribute) { XPathItem item; StringWriter omethod = new StringWriter(); foreach (XPathNavigator member in members) { 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"; mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); oattribute.Write("\t"); TypeInfo t = GetTypeDeclaration(member); oattribute.Write(t.Name); oattribute.Write(" "); oattribute.Write(mName); oattribute.WriteLine(" {"); oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] "); t.WriteAttributes(oattribute, ParameterType.Return); oattribute.WriteLine("get;"); if (!mReadOnly) { oattribute.Write("\t\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] "); t.WriteAttributes(oattribute, ParameterType.Param); oattribute.WriteLine("set;"); } oattribute.WriteLine("\t}"); } break; case "method": { String mName = member.SelectSingleNode("@name").Value; XPathNodeIterator mParamReturn = member.Select("param[@dir='return']"); omethod.WriteLine("\t[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]"); omethod.Write("\t"); bool mReturn = false; if (mParamReturn == null || mParamReturn.Count != 1) { omethod.Write("void"); } else { mParamReturn.MoveNext(); mReturn = true; WriteTypeDeclaration(omethod, mParamReturn.Current, ParameterType.Return); } mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); omethod.Write(" "); omethod.Write(mName); omethod.Write("("); XPathNodeIterator mParams = member.Select("param"); bool first = true; if (mParams.MoveNext()) { while (true) { XPathNavigator mParam = mParams.Current; String pDir = mParam.SelectSingleNode("@dir").Value; if (pDir == "return" && mReturn) { if (mParams.MoveNext()) { continue; } else { break; } } else if (pDir == "in") { } else if (pDir == "out") { } else { Console.Error.WriteLine("Unsupported parameter direction {0}", pDir); } if (first) { first = false; } else { omethod.Write(", "); } WriteTypeDeclaration(omethod, mParam, pDir == "out" ? ParameterType.Out : ParameterType.In); omethod.Write(" p"); omethod.Write(mParam.SelectSingleNode("@name").Value); if (!mParams.MoveNext()) break; } } omethod.WriteLine(");"); } break; default: Console.Error.WriteLine("Unknown member type {0}", member.Name); break; } } oattribute.Write((omethod as StringWriter).ToString()); } private static TypeInfo GetTypeDeclaration(XPathNavigator nav) { ParameterType pt = ParameterType.Param; return GetTypeDeclaration(nav, ref pt); } private static void WriteTypeDeclaration(TextWriter o, XPathNavigator nav, ParameterType paramType) { TypeInfo t = GetTypeDeclaration(nav, ref paramType); t.WriteDeclaration(o, paramType); } private static 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)) { Console.Error.WriteLine("Type {0} is not supported", mType); t = new TypeInfo("void"); } if (mMod == "ptr") { if (paramType == ParameterType.In) { paramType = ParameterType.Reference; } else { t = new TypeInfo("IntPtr"); } } else if (mMod == "string") { t = new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)"); } else if (mMod != null) { Console.Error.WriteLine("Type modifier {0} is not supported", mMod); t = new TypeInfo("void"); } if (pArray) { t = new TypeInfo("Array", "MarshalAs(UnmanagedType.SafeArray)"); if (paramType == ParameterType.In || paramType == ParameterType.Out) paramType = ParameterType.Reference; } return t; } }