From 9140982ef3f3af0dc2192414a3447a75f2748446 Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Mon, 4 Jan 2021 16:16:09 +0100 Subject: [PATCH 1/4] Gir: Add virtual methods --- Generator/Gir/GClass.cs | 3 +++ Generator/Gir/GVirtualMethod.cs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 Generator/Gir/GVirtualMethod.cs diff --git a/Generator/Gir/GClass.cs b/Generator/Gir/GClass.cs index 0352d348b..f193f3166 100644 --- a/Generator/Gir/GClass.cs +++ b/Generator/Gir/GClass.cs @@ -20,6 +20,9 @@ public class GClass : GInterface [XmlElement ("field")] public List Fields { get; set; } = default!; + [XmlElement("virtual-method")] + public List VirtualMethods { get; set; } = default!; + [XmlAttribute("parent")] public string? Parent { get; set; } diff --git a/Generator/Gir/GVirtualMethod.cs b/Generator/Gir/GVirtualMethod.cs new file mode 100644 index 000000000..1e842189c --- /dev/null +++ b/Generator/Gir/GVirtualMethod.cs @@ -0,0 +1,16 @@ +using System.Xml.Serialization; + +namespace Gir +{ + public class GVirtualMethod : GMethod + { + #region Properties + + [XmlAttribute("invoker")] + public string? Invoker { get; set; } + + public bool HasInvoker => Invoker is not null; + + #endregion + } +} From 950b77d2e1b8293923ea2f236c4511b539628b2c Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Mon, 4 Jan 2021 19:35:00 +0100 Subject: [PATCH 2/4] Testcode virtual methods --- Generator/Resolver/TypeResolver.cs | 18 +++++++-- Generator/Templates/Shared/struct.sbntxt | 2 +- Libs/Directory.Build.props | 1 + Libs/GObject/Classes/Object.cs | 2 +- Libs/Gtk3/Classes/Button.cs | 3 ++ Samples/Gtk3/QuickStart/Program.cs | 47 ++++++++++++++++++++++- Samples/Gtk3/QuickStart/QuickStart.csproj | 1 + 7 files changed, 66 insertions(+), 8 deletions(-) diff --git a/Generator/Resolver/TypeResolver.cs b/Generator/Resolver/TypeResolver.cs index e8eed4dcc..ae02218e8 100644 --- a/Generator/Resolver/TypeResolver.cs +++ b/Generator/Resolver/TypeResolver.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Gir; namespace Generator @@ -29,8 +31,6 @@ public ResolvedType(string type, Direction dir = Direction.Value, string attribu public override string ToString() => GetTypeString(); - // public string GetTypeString() => Attribute + (IsRef ? "ref " : string.Empty) + Type; - public string GetTypeString() => Attribute + Direction switch { Direction.Value => Type, @@ -42,7 +42,6 @@ public ResolvedType(string type, Direction dir = Direction.Value, string attribu }; public string GetFieldString() => Direction == Direction.Value ? Type : "IntPtr"; - #endregion #region IEquatable Implementation @@ -125,7 +124,7 @@ public TypeResolver(AliasResolver resolver) public ResolvedType Resolve(IType typeInfo) => typeInfo switch { - GField f when f.Callback is { } => new ResolvedType("IntPtr"), + GField f when f.Callback is { } c => ResolveCallback(c), { Array: { CType: { } n } } when n.EndsWith("**") => new ResolvedType("IntPtr", Direction.InOut), { Type: { } gtype } => GetTypeName(ConvertGType(gtype, typeInfo is GParameter, typeInfo)), { Array: { Length: { } length, Type: { CType: { } } gtype } } => GetTypeName(ResolveArrayType(gtype, typeInfo is GParameter, length)), @@ -134,6 +133,17 @@ public TypeResolver(AliasResolver resolver) { Array: { } } => new ResolvedType("IntPtr"), _ => throw new NotSupportedException("Type is missing supported Type information") }; + + private ResolvedType ResolveCallback(GCallback callback) + { + ResolvedType returntype = Resolve(callback.ReturnValue ?? throw new Exception("Missing return for callback")); + + List parameters = callback.Parameters?.AllParameters.Select(Resolve).ToList() ?? new (); + parameters.Add(returntype); + + var parametersString = string.Join(", ", parameters.Select(x => x.GetFieldString())); + return new ResolvedType($"unsafe delegate* unmanaged[Cdecl]<{parametersString}>"); + } private MyType StringArray(string length, bool isParameter) => new MyType("byte") { diff --git a/Generator/Templates/Shared/struct.sbntxt b/Generator/Templates/Shared/struct.sbntxt index 47efd1a90..3fcd914a4 100644 --- a/Generator/Templates/Shared/struct.sbntxt +++ b/Generator/Templates/Shared/struct.sbntxt @@ -9,7 +9,7 @@ namespace {{ namespace }} {{ include 'header.sbntxt' this ~}} [StructLayout(LayoutKind.Sequential)] - public partial struct {{ name }} + public unsafe partial struct {{ name }} { #region Fields {{~ for field in fields }} diff --git a/Libs/Directory.Build.props b/Libs/Directory.Build.props index 1f0c16380..60d3ff365 100644 --- a/Libs/Directory.Build.props +++ b/Libs/Directory.Build.props @@ -11,6 +11,7 @@ https://github.com/GirCore/gir.core MIT snupkg + true diff --git a/Libs/GObject/Classes/Object.cs b/Libs/GObject/Classes/Object.cs index 9a6426e21..5574e3230 100644 --- a/Libs/GObject/Classes/Object.cs +++ b/Libs/GObject/Classes/Object.cs @@ -106,7 +106,7 @@ public Object(params ConstructParameter[] properties) } /// - /// Initializes a wrapper for an existing object + /// Initializes a wrapper for an existing objectTypedes /// /// protected Object(IntPtr handle) diff --git a/Libs/Gtk3/Classes/Button.cs b/Libs/Gtk3/Classes/Button.cs index efcb6718e..a2aa152f3 100644 --- a/Libs/Gtk3/Classes/Button.cs +++ b/Libs/Gtk3/Classes/Button.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using GLib; using GObject; @@ -128,5 +129,7 @@ public bool UseActionAppearance } #endregion + + } } diff --git a/Samples/Gtk3/QuickStart/Program.cs b/Samples/Gtk3/QuickStart/Program.cs index 8db813358..05b9c32ee 100644 --- a/Samples/Gtk3/QuickStart/Program.cs +++ b/Samples/Gtk3/QuickStart/Program.cs @@ -1,4 +1,7 @@ -using Gtk; +using System; +using System.Runtime.InteropServices; +using GObject; +using Gtk; using Global = Gtk.Global; namespace GtkDemo @@ -46,7 +49,7 @@ public static void Main(string[] args) // Add some widgets to the notebook ["Page1"] = new Label("Hello C#"), - ["Page2"] = new Button("Open") + ["Page2"] = new MyButton("Open") { // Register a callback for the button [Button.ClickedSignal] = OnOpenButtonClick, @@ -131,4 +134,44 @@ public static void OnCloseButtonClick(Button sender, System.EventArgs args) #endregion } + + public class MyButton : Button + { + private static Button.delPressed delPressedOrig; + + private static unsafe void ClassInit(GObject.Type gClass, System.Type type, IntPtr classData) + { + var _buttonClass = (ButtonClass*) TypeHelper.GetClassPointer(gClass); + _buttonClass->pressed = Marshal.GetFunctionPointerForDelegate(StaticPressed); + + var parent = GObject.Global.Native.type_parent(gClass.Value); + var parentbuttonClass = (ButtonClass*) TypeHelper.GetClassPointer(new GObject.Type(parent)); + delPressedOrig = Marshal.GetDelegateForFunctionPointer(parentbuttonClass->pressed); + } + + public MyButton(string label) : base(label) + { + + } + + private static void StaticPressed(nint instance) + { + if (TryWrapHandle(instance, out var obj)) + { + obj.Pressed(); + } + } + + private void BasePressed() + { + delPressedOrig(Handle); + } + + //[Overrides(VirtualMethod.Pressed)] + public void Pressed() + { + BasePressed(); + Console.WriteLine("bla"); + } + } } diff --git a/Samples/Gtk3/QuickStart/QuickStart.csproj b/Samples/Gtk3/QuickStart/QuickStart.csproj index 3478c0fe0..c21a7410f 100644 --- a/Samples/Gtk3/QuickStart/QuickStart.csproj +++ b/Samples/Gtk3/QuickStart/QuickStart.csproj @@ -5,6 +5,7 @@ + true Exe net5.0 enable From 06c37c55fda361a9b6cec9ab4787209db28e6864 Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Thu, 7 Jan 2021 18:37:01 +0100 Subject: [PATCH 3/4] Updates --- Generator/Resolver/TypeResolver.cs | 2 +- Libs/GObject/Classes/Global.cs | 8 ++++++++ Samples/Gtk3/QuickStart/Program.cs | 27 +++++++++++++-------------- 3 files changed, 22 insertions(+), 15 deletions(-) create mode 100644 Libs/GObject/Classes/Global.cs diff --git a/Generator/Resolver/TypeResolver.cs b/Generator/Resolver/TypeResolver.cs index ae02218e8..cb0f5c192 100644 --- a/Generator/Resolver/TypeResolver.cs +++ b/Generator/Resolver/TypeResolver.cs @@ -142,7 +142,7 @@ private ResolvedType ResolveCallback(GCallback callback) parameters.Add(returntype); var parametersString = string.Join(", ", parameters.Select(x => x.GetFieldString())); - return new ResolvedType($"unsafe delegate* unmanaged[Cdecl]<{parametersString}>"); + return new ResolvedType($"unsafe delegate* unmanaged<{parametersString}>"); } private MyType StringArray(string length, bool isParameter) => new MyType("byte") diff --git a/Libs/GObject/Classes/Global.cs b/Libs/GObject/Classes/Global.cs new file mode 100644 index 000000000..c2dbade58 --- /dev/null +++ b/Libs/GObject/Classes/Global.cs @@ -0,0 +1,8 @@ +namespace GObject +{ + public static partial class Global + { + public static Type GetParentType(Type t) + => new Type(Native.type_parent(t.Value)); + } +} diff --git a/Samples/Gtk3/QuickStart/Program.cs b/Samples/Gtk3/QuickStart/Program.cs index 05b9c32ee..b59aca13a 100644 --- a/Samples/Gtk3/QuickStart/Program.cs +++ b/Samples/Gtk3/QuickStart/Program.cs @@ -137,16 +137,15 @@ public static void OnCloseButtonClick(Button sender, System.EventArgs args) public class MyButton : Button { - private static Button.delPressed delPressedOrig; + private unsafe static ButtonClass* buttonClass; private static unsafe void ClassInit(GObject.Type gClass, System.Type type, IntPtr classData) { - var _buttonClass = (ButtonClass*) TypeHelper.GetClassPointer(gClass); - _buttonClass->pressed = Marshal.GetFunctionPointerForDelegate(StaticPressed); + var myButtonClass = (ButtonClass*) TypeHelper.GetClassPointer(gClass); + myButtonClass->pressed = &StaticPressed; - var parent = GObject.Global.Native.type_parent(gClass.Value); - var parentbuttonClass = (ButtonClass*) TypeHelper.GetClassPointer(new GObject.Type(parent)); - delPressedOrig = Marshal.GetDelegateForFunctionPointer(parentbuttonClass->pressed); + var buttonType = GObject.Global.GetParentType(gClass); + buttonClass = (ButtonClass*) TypeHelper.GetClassPointer(buttonType); } public MyButton(string label) : base(label) @@ -154,6 +153,7 @@ public MyButton(string label) : base(label) } + [UnmanagedCallersOnly] private static void StaticPressed(nint instance) { if (TryWrapHandle(instance, out var obj)) @@ -161,17 +161,16 @@ private static void StaticPressed(nint instance) obj.Pressed(); } } - - private void BasePressed() - { - delPressedOrig(Handle); - } - + + //This could be a potential attribute to trigger code generation for virtual methods //[Overrides(VirtualMethod.Pressed)] public void Pressed() { - BasePressed(); - Console.WriteLine("bla"); + unsafe + { + buttonClass->pressed(Handle); + } + Console.WriteLine("TestTest"); } } } From d862c64dab32cd6a848846343241fd68830c80fc Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Thu, 7 Jan 2021 18:54:24 +0100 Subject: [PATCH 4/4] Update --- Samples/Gtk3/QuickStart/Program.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Samples/Gtk3/QuickStart/Program.cs b/Samples/Gtk3/QuickStart/Program.cs index b59aca13a..bf4ee411f 100644 --- a/Samples/Gtk3/QuickStart/Program.cs +++ b/Samples/Gtk3/QuickStart/Program.cs @@ -162,14 +162,19 @@ private static void StaticPressed(nint instance) } } - //This could be a potential attribute to trigger code generation for virtual methods - //[Overrides(VirtualMethod.Pressed)] - public void Pressed() + private void BasePressed() { unsafe { buttonClass->pressed(Handle); } + } + + //This could be a potential attribute to trigger code generation for virtual methods + //[Overrides(VirtualMethod.Pressed)] + public void Pressed() + { + BasePressed(); Console.WriteLine("TestTest"); } }