Generator: make interfaces partial, make filter files more expressive. Update qt bindings to build correctly out of the box

This commit is contained in:
Alexander Corrado 2011-08-15 03:39:12 -04:00
Родитель cb888f8440
Коммит 6a2a76216a
14 изменённых файлов: 148 добавлений и 54 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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 ();

Просмотреть файл

@ -1,9 +0,0 @@
QObject
QApplication
QCoreApplication
QWidget
QAbstractButton
QPushButton
QPaintDevice
QString
QSize

27
qt/qt-gui-filters.xml Normal file
Просмотреть файл

@ -0,0 +1,27 @@
<!--
This XML filter file format.
There are 3 different modes:
Include -> include this type in the generated output
Exclude -> do not include this type in the generated output. methods using this type will be removed (virtual methods will be stubbed with IntPtr)
External -> do not include this type in the generated output, but expect an implementation to be provided
The type of external implementation can be specified:
class (default) -> this type is implemented as a managed reference type
struct -> this type is implemented as a managed value type. when passed as pointer or reference, the managed "ref" prefix will be used
The default behavior is Include. Change the default by specifying the default attribute on the top-level Filter tag.
Specify exceptions to the default behavior with child nodes named after one of the modes above…
-->
<Filter default="Exclude">
<Include>QObject</Include>
<Include>QApplication</Include>
<Include>QCoreApplication</Include>
<Include>QWidget</Include>
<Include>QAbstractButton</Include>
<Include>QPushButton</Include>
<Include>QPaintDevice</Include>
<External implementation="struct">QString</External>
<External implementation="struct">QSize</External>
</Filter>

Просмотреть файл

@ -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 ();

Просмотреть файл

@ -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)

20
qt/src/QPushButton.cs Normal file
Просмотреть файл

@ -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)
{
}
}
}

36
src/generator/Filter.cs Normal file
Просмотреть файл

@ -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<string, Filter> 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<Filter,string> (r => r.TypeName);
}
}

Просмотреть файл

@ -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<Class> Classes { get; set; }
public Dictionary<Node, Class> NodeToClass { get; set; }
public Dictionary<string, string> Filters { get; set; }
private FilterMode default_filter_mode;
public FilterMode DefaultFilterMode { get { return default_filter_mode; } set { default_filter_mode = value; } }
public Dictionary<string, Filter> 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 <string, string> ();
foreach (string s in File.ReadAllLines (file)) {
Filters [s] = s;
}
}
void CreateClasses (Node root) {
List<Node> 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<Node> classNodes = root.Children.Where (o =>
(o.Type == "Class" ||
o.Type == "Struct") &&
!(o.IsTrue ("incomplete") ||
!o.HasValue ("name")
)).ToList ();
List<Class> classes = new List<Class> ();
NodeToClass = new Dictionary <Node, Class> ();
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 };
}
}

Просмотреть файл

@ -51,6 +51,7 @@ FILES = \
Access.cs \
Class.cs \
Field.cs \
Filter.cs \
Generator.cs \
Method.cs \
Node.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<Parameter> 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 ");

Просмотреть файл

@ -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<Parameter> 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 ();

Просмотреть файл

@ -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) {

Просмотреть файл

@ -71,6 +71,7 @@
<Compile Include="Access.cs" />
<Compile Include="Templates\CSharp\CSharpLanguage.cs" />
<Compile Include="Templates\Context.cs" />
<Compile Include="Filter.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System">