view InteropCodeGen/gendotnet.cs @ 1:55ca098c88d0

Added disclaimer
author Ivo Smits
date Wed, 04 May 2011 01:06:22 +0200
parents e1ec7bf71313
children f1deea9c97a0
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 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;
	}
}