diff --git a/qt/Makefile.am b/qt/Makefile.am index 772b9a62..d43bee2a 100644 --- a/qt/Makefile.am +++ b/qt/Makefile.am @@ -29,7 +29,6 @@ generated: qt-gui-filters.xml qt-gui.xml # $(CXX) -m32 -I. -framework QtGui -framework QtCore -DQ_WS_MAC --shared -fPIC -o $@ -fkeep-inline-functions qt-gui.cpp Qt.Gui-binding.dll: generated $(addprefix src/,$(HANDWRITTEN)) - $(RM) -f generated/QString.cs generated/QSize.cs $(GMCS) -debug -out:$@ -target:library -unsafe -r:$(INTEROP_DLL) generated/*.cs $(addprefix src/,$(HANDWRITTEN)) hello.exe: Qt.Gui-binding.dll demos/hello.cs #libQtGui-inline.so diff --git a/qt/demos/hello.cs b/qt/demos/hello.cs index 6f89fb68..2fb6c655 100644 --- a/qt/demos/hello.cs +++ b/qt/demos/hello.cs @@ -9,9 +9,10 @@ namespace QtTest { public static void Main (string[] args) { using (QApplication app = new QApplication ()) { - using (QPushButton hello = new QPushButton ("Hello world!", null)) { + using (QPushButton hello = new QPushButton ("Hello world!")) { - hello.Resize (new QSize (100, 30)); + var sz = new QSize (100, 30); + hello.Resize (ref sz); hello.SetVisible (true); QApplication.Exec (); diff --git a/qt/qt-gui-filters.txt b/qt/qt-gui-filters.txt deleted file mode 100644 index ec79d949..00000000 --- a/qt/qt-gui-filters.txt +++ /dev/null @@ -1,9 +0,0 @@ -QObject -QApplication -QCoreApplication -QWidget -QAbstractButton -QPushButton -QPaintDevice -QString -QSize diff --git a/qt/qt-gui-filters.xml b/qt/qt-gui-filters.xml new file mode 100644 index 00000000..c0e32252 --- /dev/null +++ b/qt/qt-gui-filters.xml @@ -0,0 +1,27 @@ + + + + QObject + QApplication + QCoreApplication + QWidget + QAbstractButton + QPushButton + QPaintDevice + QString + QSize + diff --git a/qt/src/QApplication.cs b/qt/src/QApplication.cs index 8b3d698f..99fb8336 100644 --- a/qt/src/QApplication.cs +++ b/qt/src/QApplication.cs @@ -4,8 +4,11 @@ using Mono.Cxxi; namespace Qt.Gui { public partial class QApplication { - - + + public partial interface IQApplication { + [Constructor] CppInstancePtr QApplication (CppInstancePtr @this, [MangleAs ("int&")] IntPtr argc, [MangleAs ("char**")] IntPtr argv, int version); + } + public QApplication () : base (impl.TypeInfo) { InitArgcAndArgv (); diff --git a/qt/src/QCoreApplication.cs b/qt/src/QCoreApplication.cs index f40afced..399ee49b 100644 --- a/qt/src/QCoreApplication.cs +++ b/qt/src/QCoreApplication.cs @@ -5,6 +5,10 @@ using Mono.Cxxi; namespace Qt.Gui { public partial class QCoreApplication { + public partial interface IQCoreApplication { + [Constructor] CppInstancePtr QCoreApplication (CppInstancePtr @this, [MangleAs ("int&")] IntPtr argc, [MangleAs ("char**")] IntPtr argv); + } + protected IntPtr argc, argv; public QCoreApplication () : base (impl.TypeInfo) diff --git a/qt/src/QPushButton.cs b/qt/src/QPushButton.cs new file mode 100644 index 00000000..3e615fdf --- /dev/null +++ b/qt/src/QPushButton.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.InteropServices; +using Mono.Cxxi; + +namespace Qt.Gui { + public partial class QPushButton { + + public QPushButton (QString text, QWidget parent) + : this (ref text, parent) + { + } + + public QPushButton (QString text) + : this (ref text, null) + { + } + + } +} + diff --git a/src/generator/Filter.cs b/src/generator/Filter.cs new file mode 100644 index 00000000..342a80c4 --- /dev/null +++ b/src/generator/Filter.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using System.Xml.Linq; +using System.Collections.Generic; + +public enum FilterMode { + Include, + Exclude, + External +} + +public enum ImplementationType { + @class, + @struct +} + +public struct Filter { + + public string TypeName { get; set; } + public FilterMode Mode { get; set; } + public ImplementationType ImplType { get; set; } + + public static Dictionary Load (XDocument doc, out FilterMode @default) + { + string value; + @default = (value = (string)doc.Root.Attribute ("default")) != null ? (FilterMode)Enum.Parse (typeof (FilterMode), value) : FilterMode.Include; + + var rules = from rule in doc.Root.Elements () + let mode = (FilterMode)Enum.Parse (typeof (FilterMode), rule.Name.LocalName) + let impl = (value = (string)rule.Attribute ("implementation")) != null ? (ImplementationType)Enum.Parse (typeof (ImplementationType), value) : ImplementationType.@class + select new Filter { TypeName = rule.Value, Mode = mode, ImplType = impl }; + + + return rules.ToDictionary (r => r.TypeName); + } +} \ No newline at end of file diff --git a/src/generator/Generator.cs b/src/generator/Generator.cs index 4c77b61b..e0103a49 100644 --- a/src/generator/Generator.cs +++ b/src/generator/Generator.cs @@ -7,6 +7,7 @@ using System; using System.IO; using System.Collections.Generic; using System.Xml; +using System.Xml.Linq; using System.Linq; using System.Reflection; @@ -27,7 +28,10 @@ public class Generator { // Classes to generate code for public List Classes { get; set; } public Dictionary NodeToClass { get; set; } - public Dictionary Filters { get; set; } + + private FilterMode default_filter_mode; + public FilterMode DefaultFilterMode { get { return default_filter_mode; } set { default_filter_mode = value; } } + public Dictionary Filters { get; set; } // Code templates public ITemplate Libs { get; set; } @@ -47,7 +51,7 @@ public class Generator { Node root = LoadXml (InputFileName); if (FilterFile != null) - LoadFilters (FilterFile); + Filters = Filter.Load (XDocument.Load (FilterFile), out default_filter_mode); CreateClasses (root); @@ -147,29 +151,27 @@ public class Generator { return root; } - void LoadFilters (string file) { - Filters = new Dictionary (); - foreach (string s in File.ReadAllLines (file)) { - Filters [s] = s; - } - } - void CreateClasses (Node root) { - List classNodes = root.Children.Where (o => o.Type == "Class" || o.Type == "Struct").ToList (); - classNodes.RemoveAll (o => o.IsTrue ("incomplete") || !o.HasValue ("name")); - - if (Filters != null) - classNodes.RemoveAll (o => !Filters.ContainsKey (o.Name)); + List classNodes = root.Children.Where (o => + (o.Type == "Class" || + o.Type == "Struct") && + !(o.IsTrue ("incomplete") || + !o.HasValue ("name") + )).ToList (); List classes = new List (); NodeToClass = new Dictionary (); foreach (Node n in classNodes) { - Console.WriteLine (n.Name); + var filter = GetFilterOrDefault (n.Name); + if (filter.Mode == FilterMode.Exclude) + continue; - Class klass = new Class (n); - classes.Add (klass); + var klass = new Class (n); NodeToClass [n] = klass; + + if (filter.Mode != FilterMode.External) + classes.Add (klass); } // Compute bases @@ -429,7 +431,7 @@ public class Generator { // Return the System.Type name corresponding to T, or null // Returned as a string, because other wrappers do not have System.Types yet - public static string CppTypeToManaged (CppType t) { + public string CppTypeToManaged (CppType t) { Type mtype = t.ToManagedType (); if (mtype != null && mtype != typeof (ICppObject)) { @@ -441,7 +443,12 @@ public class Generator { case CppTypes.Class: case CppTypes.Struct: // FIXME: Full name - return t.ElementTypeName; + + var filter = GetFilterOrDefault (t.ElementTypeName); + if (filter.ImplType == ImplementationType.@struct) + return t.ElementTypeName + "&"; + else + return t.ElementTypeName; } @@ -470,4 +477,13 @@ public class Generator { } } } + + Filter GetFilterOrDefault (string typeName) + { + Filter result; + if (Filters != null && Filters.TryGetValue (typeName, out result)) + return result; + + return new Filter { TypeName = typeName, Mode = default_filter_mode }; + } } diff --git a/src/generator/Makefile.am b/src/generator/Makefile.am index 68129c31..34b7d887 100644 --- a/src/generator/Makefile.am +++ b/src/generator/Makefile.am @@ -51,6 +51,7 @@ FILES = \ Access.cs \ Class.cs \ Field.cs \ + Filter.cs \ Generator.cs \ Method.cs \ Node.cs \ diff --git a/src/generator/Templates/CSharp/CSharpClass.cs b/src/generator/Templates/CSharp/CSharpClass.cs index 6544ffa4..328ac657 100644 --- a/src/generator/Templates/CSharp/CSharpClass.cs +++ b/src/generator/Templates/CSharp/CSharpClass.cs @@ -23,7 +23,7 @@ namespace Templates { private void WriteMethodHeader (Method method, string layoutClass, bool isNonPrimaryOverride, bool @protected) { - var returnType = CSharpLanguage.TypeName (method.ReturnType, Context.Wrapper | Context.Return); + var returnType = CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Wrapper | Context.Return); if (!isNonPrimaryOverride && method.IsVirtual) WriteLine ("[OverrideNative (\"{0}\")]", method.Name); @@ -63,7 +63,7 @@ private void WriteParameters (IList parameters, bool writeType, bool if (i != 0) Write (", "); - var type = CSharpLanguage.TypeName (parameters [i].Type, Context.Parameter); + var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (parameters [i].Type), Context.Parameter); if (writeAttributes) { var mangleAs = parameters [i].Type.ToString (); @@ -283,7 +283,7 @@ private bool IsByVal (CppType t) #line hidden #line 35 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write("\t\tpublic interface "); + this.Write("\t\tpublic partial interface "); #line default #line hidden @@ -332,7 +332,7 @@ private bool IsByVal (CppType t) if (method.IsConstructor) Write ("CppInstancePtr"); else - Write (CSharpLanguage.TypeName (method.ReturnType, Context.Interface | Context.Return)); + Write (CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Interface | Context.Return)); Write (" "); Write (CSharpLanguage.SafeIdentifier (method.Name)); @@ -347,7 +347,7 @@ private bool IsByVal (CppType t) Write (");\n"); } foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { - WriteLine ("CppField<{0}> {1} {{ get; }}", CSharpLanguage.TypeName (field.Type, Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); + WriteLine ("CppField<{0}> {1} {{ get; }}", CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); } ClearIndent (); @@ -397,7 +397,7 @@ private bool IsByVal (CppType t) #line hidden #line 77 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt" - this.Write(this.ToStringHelper.ToStringWithCulture( CSharpLanguage.TypeName (field.Type, Context.Generic) )); + this.Write(this.ToStringHelper.ToStringWithCulture( CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic) )); #line default #line hidden @@ -442,7 +442,7 @@ private bool IsByVal (CppType t) PushIndent ("\t\t"); foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { var fieldName = CSharpLanguage.SafeIdentifier (field.Name); - WriteLine ("{0} {1} {2} {{", field.Access, CSharpLanguage.TypeName (field.Type, Context.Wrapper | Context.Return), fieldName); + WriteLine ("{0} {1} {2} {{", field.Access, CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Wrapper | Context.Return), fieldName); #line default #line hidden @@ -628,7 +628,7 @@ private bool IsByVal (CppType t) PushIndent ("\t\t"); foreach (var prop in Class.Properties) { var propName = CSharpLanguage.SafeIdentifier (prop.Name); - var type = CSharpLanguage.TypeName (prop.Type, Context.Wrapper | Context.Return); + var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (prop.Type), Context.Wrapper | Context.Return); Write (CurrentIndent + "public "); diff --git a/src/generator/Templates/CSharp/CSharpClass.tt b/src/generator/Templates/CSharp/CSharpClass.tt index 22792123..a3081426 100644 --- a/src/generator/Templates/CSharp/CSharpClass.tt +++ b/src/generator/Templates/CSharp/CSharpClass.tt @@ -32,7 +32,7 @@ namespace <#= Generator.Namespace #> { <# } #> <# /* Interface */ #> - public interface <#= iface #> : ICppClassOverridable<<#= wrapper #>> { + public partial interface <#= iface #> : ICppClassOverridable<<#= wrapper #>> { <# PushIndent ("\t\t\t"); foreach (var method in Class.Methods) { Write (CurrentIndent); @@ -52,7 +52,7 @@ namespace <#= Generator.Namespace #> { if (method.IsConstructor) Write ("CppInstancePtr"); else - Write (CSharpLanguage.TypeName (method.ReturnType, Context.Interface | Context.Return)); + Write (CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Interface | Context.Return)); Write (" "); Write (CSharpLanguage.SafeIdentifier (method.Name)); @@ -67,14 +67,14 @@ namespace <#= Generator.Namespace #> { Write (");\n"); } foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { - WriteLine ("CppField<{0}> {1} {{ get; }}", CSharpLanguage.TypeName (field.Type, Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); + WriteLine ("CppField<{0}> {1} {{ get; }}", CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic), CSharpLanguage.SafeIdentifier (field.Name)); } ClearIndent (); #> } <# /* Native layout */ #> private struct <#= layout #> { <# foreach (var field in Class.Fields) { #> - public <#= CSharpLanguage.TypeName (field.Type, Context.Generic) #> <#= CSharpLanguage.SafeIdentifier (field.Name) #>; + public <#= CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Generic) #> <#= CSharpLanguage.SafeIdentifier (field.Name) #>; <# } #> } @@ -82,7 +82,7 @@ namespace <#= Generator.Namespace #> { <# PushIndent ("\t\t"); foreach (var field in Class.Fields.Where (f => f.Access != Access.@private)) { var fieldName = CSharpLanguage.SafeIdentifier (field.Name); - WriteLine ("{0} {1} {2} {{", field.Access, CSharpLanguage.TypeName (field.Type, Context.Wrapper | Context.Return), fieldName); #> + WriteLine ("{0} {1} {2} {{", field.Access, CSharpLanguage.TypeName (Generator.CppTypeToManaged (field.Type), Context.Wrapper | Context.Return), fieldName); #> get { return impl.<#= fieldName #> [Native]; } @@ -138,7 +138,7 @@ namespace <#= Generator.Namespace #> { <# PushIndent ("\t\t"); foreach (var prop in Class.Properties) { var propName = CSharpLanguage.SafeIdentifier (prop.Name); - var type = CSharpLanguage.TypeName (prop.Type, Context.Wrapper | Context.Return); + var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (prop.Type), Context.Wrapper | Context.Return); Write (CurrentIndent + "public "); @@ -288,7 +288,7 @@ if (overrideInitBases || Class.BaseClasses.Count > 1) { #> <#+ private void WriteMethodHeader (Method method, string layoutClass, bool isNonPrimaryOverride, bool @protected) { - var returnType = CSharpLanguage.TypeName (method.ReturnType, Context.Wrapper | Context.Return); + var returnType = CSharpLanguage.TypeName (Generator.CppTypeToManaged (method.ReturnType), Context.Wrapper | Context.Return); if (!isNonPrimaryOverride && method.IsVirtual) WriteLine ("[OverrideNative (\"{0}\")]", method.Name); @@ -328,7 +328,7 @@ private void WriteParameters (IList parameters, bool writeType, bool if (i != 0) Write (", "); - var type = CSharpLanguage.TypeName (parameters [i].Type, Context.Parameter); + var type = CSharpLanguage.TypeName (Generator.CppTypeToManaged (parameters [i].Type), Context.Parameter); if (writeAttributes) { var mangleAs = parameters [i].Type.ToString (); diff --git a/src/generator/Templates/CSharp/CSharpLanguage.cs b/src/generator/Templates/CSharp/CSharpLanguage.cs index b07c6532..e4cf2f7b 100644 --- a/src/generator/Templates/CSharp/CSharpLanguage.cs +++ b/src/generator/Templates/CSharp/CSharpLanguage.cs @@ -27,11 +27,6 @@ namespace Templates { return keywords.Contains (proposedName)? "@" + proposedName : proposedName; } - public static string TypeName (CppType t, Context context) - { - return TypeName (Generator.CppTypeToManaged (t), context); - } - public static string TypeName (string str, Context context) { switch (str) { diff --git a/src/generator/generator.csproj b/src/generator/generator.csproj index 0caeb016..a91040f7 100644 --- a/src/generator/generator.csproj +++ b/src/generator/generator.csproj @@ -71,6 +71,7 @@ +