view InteropCodeGen/Program.cs @ 6:e640ca67b819

Added extended COM interop code generator for interfaces and proxies
author Ivo Smits
date Fri, 06 May 2011 04:02:43 +0200
parents
children a7650e26195f
line wrap: on
line source

???using System;
using System.Xml.XPath;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace VBoxSDK {
	class Program {
		public static void Main(String[] args) {
			Boolean TargetIsMono = false;

			XidlParser parser = new XidlParser();
			XPathDocument xidlDoc = new XPathDocument("VirtualBox.xidl");
			if (TargetIsMono) {
				parser.Types["wstring"] = new StringTypeInfo(UnmanagedType.LPWStr);
				parser.BaseInterfaceType = parser.Library.Interfaces["IUnknown"];
			} else {
				parser.Types["wstring"] = new StringTypeInfo(UnmanagedType.BStr);
				parser.BaseInterfaceType = parser.Library.Interfaces["IDispatch"];
			}
			parser.Parse(xidlDoc.CreateNavigator());
			foreach (InterfaceInfo intf in parser.Library.Interfaces.Values) {
				GnomeSort(intf.Members,	delegate(InterfaceMemberInfo a, InterfaceMemberInfo b) {
					if (b is PropertyInfo && a is MethodInfo) return 1;
					else if (a is PropertyInfo && b is MethodInfo) return -1;
					return 0;
				});
			}
			using (TextWriter outfile = File.CreateText("Interfaces.txt")) {
				PrintTypeTree(outfile, parser.Library);
			}
			using (TextWriter outfile = File.CreateText("Interfaces.cs")) {
				outfile.WriteLine("using System;");
				outfile.WriteLine("using System.Runtime.InteropServices;");
				outfile.WriteLine("using System.Runtime.CompilerServices;");
				outfile.WriteLine("namespace VirtualBox {");
				ComInteropInterfaceGenerator igen = new ComInteropInterfaceGenerator(outfile);
				igen.IncludeInheritedMembers = true;
				igen.IncludeComAttributes = true;
				igen.ComInterfaceTypeIDispatch = !TargetIsMono;
				igen.TypeModifiers = "public";
				igen.WriteLibrary(parser.Library);
				outfile.WriteLine("}");
			}
			parser.Library.Interfaces["IUnknown"].Members.Add(new MethodInfo("QueryInterface", new ValueTypeInfo("IntPtr")));
			(parser.Library.Interfaces["IUnknown"].Members[0] as MethodInfo).Parameters.Add(new MethodParameterInfo("riid", new ValueTypeInfo("Guid"), true, true, false));
			parser.Library.Interfaces["IUnknown"].Members.Add(new MethodInfo("AddRef", null));
			parser.Library.Interfaces["IUnknown"].Members.Add(new MethodInfo("Release", null));
			parser.Library.Interfaces["IDispatch"].Members.Add(new MethodInfo("GetTypeInfoCount", null));
			parser.Library.Interfaces["IDispatch"].Members.Add(new MethodInfo("GetTypeInfo", null));
			parser.Library.Interfaces["IDispatch"].Members.Add(new MethodInfo("GetIDsOfNames", null));
			parser.Library.Interfaces["IDispatch"].Members.Add(new MethodInfo("Invoke", null));
			parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy1", null));
			parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy2", null));
			parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy3", null));
			parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy4", null));
			parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy5", null));
			if (TargetIsMono) {
				parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy6", null));
				parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy7", null));
				parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy8", null));
				parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy9", null));
				parser.Library.Interfaces["IErrorInfo"].Members.Add(new MethodInfo("dummy10", null));
			}
			using (TextWriter outfile = File.CreateText("Proxy.cs")) {
				outfile.WriteLine("using System;");
				outfile.WriteLine("using System.Runtime.InteropServices;");
				outfile.WriteLine("using HRESULT = System.Int32;");
				outfile.WriteLine("namespace VirtualBox {");
				ComInteropProxyGenerator igen = new ComInteropProxyGenerator(outfile);
				igen.IncludeInheritedMembers = true;
				igen.TypeModifiers = "public";
				igen.WriteLibrary(parser.Library);
				outfile.WriteLine("}");
			}
			Console.WriteLine("Done.");
			Console.ReadLine();
		}
		private static void GnomeSort<T>(IList<T> a, Comparison<T> comparer) {
			int pos = 1;
			while (pos < a.Count) {
				if (comparer(a[pos], a[pos - 1]) >= 0) {
					pos++;
				} else {
					T tmp = a[pos];
					a[pos] = a[pos - 1];
					a[pos - 1] = tmp;
					if (pos > 1) pos--; else pos++;
				}
			}
		}
		private static void PrintTypeTree(TextWriter output, LibraryInfo lib) {
			foreach (KeyValuePair<String, EnumInfo> enumi in lib.Enums) {
				output.WriteLine("enum {0};", enumi.Key);
			}
			foreach (KeyValuePair<String, InterfaceInfo> intf in lib.Interfaces) {
				output.Write("interface {0}({1}) ", intf.Key, intf.Value.IID);
				if (intf.Value.Extends != null) output.Write(": {0} ", intf.Value.Extends.Name);
				output.WriteLine("{");
				foreach (InterfaceMemberInfo member in intf.Value.Members) {
					if (member is PropertyInfo) {
						PropertyInfo memberi = (PropertyInfo)member;
						output.WriteLine("property {0};", memberi.Name);
					} else if (member is MethodInfo) {
						MethodInfo memberi = (MethodInfo)member;
						output.WriteLine("method {0};", memberi.Name);
					} else {
						output.WriteLine("unknown member;");
					}
				}
				output.WriteLine("}");
			}
		}
	}
}