Generator: make interfaces partial, make filter files more expressive. Update qt bindings to build correctly out of the box
This commit is contained in:
Родитель
cb888f8440
Коммит
6a2a76216a
|
@ -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
|
|
@ -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>
|
|
@ -5,6 +5,9 @@ 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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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,6 +443,11 @@ public class Generator {
|
|||
case CppTypes.Class:
|
||||
case CppTypes.Struct:
|
||||
// FIXME: Full name
|
||||
|
||||
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">
|
||||
|
|
Загрузка…
Ссылка в новой задаче