Mercurial > hg > vboxdotnet
diff InteropCodeGen/gendotnet.cs @ 0:e1ec7bf71313
Initial commit
author | Ivo Smits |
---|---|
date | Wed, 04 May 2011 00:59:43 +0200 |
parents | |
children | f1deea9c97a0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/InteropCodeGen/gendotnet.cs Wed May 04 00:59:43 2011 +0200 @@ -0,0 +1,407 @@ +//+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 Boolean InputOnly { get; private set; } + public String Members { get; set; } + + public TypeInfo(String name, params String[] attributes) { + this.Name = name; + this.Attributes = attributes; + } + /*public TypeInfo(String name, bool inputOnly, params String[] attributes) + : this(name, attributes) { + this.InputOnly = inputOnly; + }*/ + /*public static TypeInfo CreateInterfaceWithMembers(String name, String members) { + TypeInfo ret = new TypeInfo(name, "MarshalAs(UnmanagedType.Interface)"); + ret.Members = members; + return ret; + }*/ + //Todo: if attribute mod="string"/"ptr" ... + public void WriteDeclaration(TextWriter o, ParameterType vartype) { + WriteAttributes(o, vartype); + o.Write(Name); + } + public void WriteAttributes(TextWriter o, ParameterType vartype) { + //if (InputOnly && vartype != ParameterType.In) { + 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 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("IMachine", new TypeInfo("IMachine", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("ISession", new TypeInfo("ISession", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IVirtualBox", new TypeInfo("IVirtualBox", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IHost", new TypeInfo("IHost", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IConsole", new TypeInfo("IConsole", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("ISystemProperties", new TypeInfo("ISystemProperties", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IProgress", new TypeInfo("IProgress", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IDisplay", new TypeInfo("IDisplay", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IMouse", new TypeInfo("IMouse", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IKeyboard", new TypeInfo("IKeyboard", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IFramebuffer", new TypeInfo("IFramebuffer", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IFramebufferOverlay", new TypeInfo("IFramebufferOverlay", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IMachineDebugger", new TypeInfo("IMachineDebugger", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IVirtualBoxErrorInfo", new TypeInfo("IVirtualBoxErrorInfo", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IEventSource", new TypeInfo("IEventSource", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IEventListener", new TypeInfo("IEventListener", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IEventContext", new TypeInfo("IEventContext", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IConsoleCallback", new TypeInfo("IConsoleCallback", "MarshalAs(UnmanagedType.Interface)")); + Types.Add("IEvent", new TypeInfo("IEvent", "MarshalAs(UnmanagedType.Interface)")); + + Types.Add("LockType", new TypeInfo("LockType")); + Types.Add("MediumVariant", new TypeInfo("MediumVariant")); + Types.Add("AccessMode", new TypeInfo("AccessMode")); + Types.Add("NATProtocol", new TypeInfo("NATProtocol")); + Types.Add("FirmwareType", new TypeInfo("FirmwareType")); + Types.Add("StorageControllerType", new TypeInfo("StorageControllerType")); + Types.Add("StorageBus", new TypeInfo("StorageBus")); + Types.Add("SessionType", new TypeInfo("SessionType")); + Types.Add("SessionState", new TypeInfo("SessionState")); + Types.Add("USBDeviceState", new TypeInfo("USBDeviceState")); + Types.Add("USBDeviceFilterAction", new TypeInfo("USBDeviceFilterAction")); + Types.Add("AudioControllerType", new TypeInfo("AudioControllerType")); + Types.Add("AudioDriverType", new TypeInfo("AudioDriverType")); + Types.Add("VRDPAuthType", new TypeInfo("VRDPAuthType")); + Types.Add("MachineState", new TypeInfo("MachineState")); + Types.Add("NetworkAdapterType", new TypeInfo("NetworkAdapterType")); + Types.Add("NetworkAttachmentType", new TypeInfo("NetworkAttachmentType")); + Types.Add("PortMode", new TypeInfo("PortMode")); + Types.Add("DeviceType", new TypeInfo("DeviceType")); + Types.Add("MediumState", new TypeInfo("MediumState")); + Types.Add("MediumType", new TypeInfo("MediumType")); + Types.Add("HostNetworkInterfaceType", new TypeInfo("HostNetworkInterfaceType")); + Types.Add("DeviceActivity", new TypeInfo("DeviceActivity")); + Types.Add("HostNetworkInterfaceMediumType", new TypeInfo("HostNetworkInterfaceMediumType")); + Types.Add("HostNetworkInterfaceStatus", new TypeInfo("HostNetworkInterfaceStatus")); + Types.Add("ProcessorFeature", new TypeInfo("ProcessorFeature")); + Types.Add("VFSType", new TypeInfo("VFSType")); + Types.Add("BIOSBootMenuMode", new TypeInfo("BIOSBootMenuMode")); + Types.Add("VirtualSystemDescriptionType", new TypeInfo("VirtualSystemDescriptionType")); + Types.Add("VirtualSystemDescriptionValueType", new TypeInfo("VirtualSystemDescriptionValueType")); + Types.Add("KeyboardHidType", new TypeInfo("KeyboardHidType")); + Types.Add("ClipboardMode", new TypeInfo("ClipboardMode")); + Types.Add("PointingHidType", new TypeInfo("PointingHidType")); + Types.Add("CPUPropertyType", new TypeInfo("CPUPropertyType")); + Types.Add("HWVirtExPropertyType", new TypeInfo("HWVirtExPropertyType")); + Types.Add("Scope", new TypeInfo("Scope")); + Types.Add("ChipsetType", new TypeInfo("ChipsetType")); + Types.Add("FaultToleranceState", new TypeInfo("FaultToleranceState")); + Types.Add("BandwidthGroupType", new TypeInfo("BandwidthGroupType")); + Types.Add("VBoxEventType", new TypeInfo("VBoxEventType")); + Types.Add("GuestMonitorChangedEventType", new TypeInfo("GuestMonitorChangedEventType")); + Types.Add("AuthType", new TypeInfo("AuthType")); + Types.Add("NetworkAdapterPromiscModePolicy", new TypeInfo("NetworkAdapterPromiscModePolicy")); + Types.Add("ExecuteProcessStatus", new TypeInfo("ExecuteProcessStatus")); + Types.Add("AdditionsRunLevelType", new TypeInfo("AdditionsRunLevelType")); + Types.Add("AdditionsFacilityStatus", new TypeInfo("AdditionsFacilityStatus")); + Types.Add("AdditionsFacilityType", new TypeInfo("AdditionsFacilityType")); + Types.Add("AdditionsFacilityClass", new TypeInfo("AdditionsFacilityClass")); + Types.Add("CleanupMode", new TypeInfo("CleanupMode")); + Types.Add("DataType", new TypeInfo("DataType")); + + Types.Add("IBandwidthControl", new TypeInfo("IntPtr")); + Types.Add("IVRDEServerInfo", new TypeInfo("IntPtr")); + Types.Add("IAdditionsFacility", new TypeInfo("IntPtr")); + Types.Add("IExtPackPlugIn", new TypeInfo("IntPtr")); + Types.Add("IExtPackFile", new TypeInfo("IntPtr")); + Types.Add("IExtPack", new TypeInfo("IntPtr")); + Types.Add("IBIOSSettings", new TypeInfo("IntPtr")); + Types.Add("IVFSExplorer", new TypeInfo("IntPtr")); + Types.Add("IUSBController", new TypeInfo("IntPtr")); + Types.Add("IStorageController", new TypeInfo("IntPtr")); + Types.Add("IVRDPServer", new TypeInfo("IntPtr")); + Types.Add("ISnapshot", new TypeInfo("IntPtr")); + Types.Add("INATEngine", new TypeInfo("IntPtr")); + Types.Add("IUSBDeviceFilter", new TypeInfo("IntPtr")); + Types.Add("IMediumAttachment", new TypeInfo("IntPtr")); + Types.Add("IUSBDevice", new TypeInfo("IntPtr")); + Types.Add("IParallelPort", new TypeInfo("IntPtr")); + Types.Add("ISerialPort", new TypeInfo("IntPtr")); + Types.Add("INetworkAdapter", new TypeInfo("IntPtr")); + Types.Add("IMedium", new TypeInfo("IntPtr")); + Types.Add("IGuestOSType", new TypeInfo("IntPtr")); + Types.Add("ISharedFolder", new TypeInfo("IntPtr")); + Types.Add("IPerformanceCollector", new TypeInfo("IntPtr")); + Types.Add("IDHCPServer", new TypeInfo("IntPtr")); + Types.Add("IAppliance", new TypeInfo("IntPtr")); + Types.Add("IVirtualBoxCallback", new TypeInfo("IntPtr")); + Types.Add("IPerformanceMetric", new TypeInfo("IntPtr")); + Types.Add("IMediumFormat", new TypeInfo("IntPtr")); + Types.Add("IHostUSBDevice", new TypeInfo("IntPtr")); + Types.Add("IHostNetworkInterface", new TypeInfo("IntPtr")); + Types.Add("IHostUSBDeviceFilter", new TypeInfo("IntPtr")); + Types.Add("IRemoteDisplayInfo", new TypeInfo("IntPtr")); + Types.Add("IGuest", new TypeInfo("IntPtr")); + Types.Add("IVirtualSystemDescription", new TypeInfo("IntPtr")); + Types.Add("IAudioAdapter", new TypeInfo("IntPtr")); + Types.Add("IExtPackManager", new TypeInfo("IntPtr")); + Types.Add("IVRDEServer", new TypeInfo("IntPtr")); + Types.Add("IPciDeviceAttachment", new TypeInfo("IntPtr")); + Types.Add("IBandwidthGroup", new TypeInfo("IntPtr")); + + Types.Add("$unknown", new TypeInfo("IntPtr")); + } + 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; + //String mType = member.SelectSingleNode("@type").Value; + item = member.SelectSingleNode("@readonly"); + Boolean mReadOnly = item == null ? false : item.Value == "yes"; + //item = member.SelectSingleNode("@mod"); + //String mMod = item == null ? null : item.Value; + mName = mName.Substring(0, 1).ToUpper() + mName.Substring(1); + oattribute.Write("\t"); + /*TypeInfo t; + if (mMod == "ptr") { + t = new TypeInfo("IntPtr"); + } else if (mMod == "string") { + t = new TypeInfo("String", "MarshalAs(UnmanagedType.LPWStr)"); + } else if (mMod == null) { + if (!Types.TryGetValue(mType, out t)) { + Console.Error.WriteLine("Type {0} is not supported", mType); + t = new TypeInfo("void"); + } + } else { + Console.Error.WriteLine("Type modifier {0} is not supported", mMod); + t = new TypeInfo("void"); + }*/ + 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; + TypeInfo t = GetTypeDeclaration(mParamReturn.Current); + /*String mType = mParamReturn.Current.SelectSingleNode("@type").Value; + TypeInfo t; + if (!Types.TryGetValue(mType, out t)) { + Console.Error.WriteLine("Type {0} is not supported", mType); + t = new TypeInfo("void"); + mReturn = false; + }*/ + t.WriteDeclaration(omethod, 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; + //item = mParam.SelectSingleNode("@safearray"); + //Boolean pArray = item == null ? false : item.Value == "yes"; + //item = mParam.SelectSingleNode("@mod"); + //String pMod = item == null ? null : item.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(", "); + } + ParameterType pt = ParameterType.In; + if (pDir == "out") pt = ParameterType.Out; + TypeInfo t = GetTypeDeclaration(mParam, ref pt); + t.WriteDeclaration(omethod, pt); + /*if (pArray) { + omethod.Write("[MarshalAs(UnmanagedType.SafeArray)] "); + if (pDir == "out") omethod.Write("out "); + else omethod.Write("ref "); + omethod.Write("System.Array"); + } else { + String pType = mParam.SelectSingleNode("@type").Value; + TypeInfo t; + if (!Types.TryGetValue(pType, out t)) { + Console.Error.WriteLine("Type {0} is not supported", pType); + t = new TypeInfo("IntPtr"); + mReturn = false; + } + if (pMod == "ptr") { + t.WriteDeclaration(omethod, ParameterType.Reference); + } else if (pDir == "out") { + t.WriteDeclaration(omethod, ParameterType.Out); + } else { + t.WriteDeclaration(omethod, 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 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; + } +}