From f98b6674994fa83dd6b607c6ce0eb129167ba2b7 Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:18:17 +0100 Subject: [PATCH] Avoid marshalling of instance data --- src/Libs/GObject-2.0/Internal/ObjectWrapper.cs | 13 ++++++------- src/Native/GirTestLib/girtest-class-tester.c | 13 +++++++++++++ src/Native/GirTestLib/girtest-class-tester.h | 3 +++ src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs | 11 +++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Libs/GObject-2.0/Internal/ObjectWrapper.cs b/src/Libs/GObject-2.0/Internal/ObjectWrapper.cs index 796de78c7..48640d48b 100644 --- a/src/Libs/GObject-2.0/Internal/ObjectWrapper.cs +++ b/src/Libs/GObject-2.0/Internal/ObjectWrapper.cs @@ -1,7 +1,7 @@ using System; using System.Diagnostics; using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using GLib; namespace GObject.Internal; @@ -78,16 +78,15 @@ public static T WrapInterfaceHandle(IntPtr handle, bool ownedRef) where T : c return (T) ctor.Invoke(new object[] { handle, ownedRef }); } - private static Type GetTypeFromInstance(IntPtr handle) + private static unsafe Type GetTypeFromInstance(IntPtr handle) { - TypeInstanceData instance = Marshal.PtrToStructure(handle); - TypeClassData klass = Marshal.PtrToStructure(instance.GClass); - var typeid = klass.GType; + var gclass = Unsafe.AsRef((void*) handle).GClass; + var gtype = Unsafe.AsRef((void*) gclass).GType; - if (typeid == 0) + if (gtype == 0) throw new Exception("Could not retrieve type from class struct - is the struct valid?"); - return new Type(typeid); + return new Type(gtype); } private static ConstructorInfo? GetObjectConstructor(System.Type type) diff --git a/src/Native/GirTestLib/girtest-class-tester.c b/src/Native/GirTestLib/girtest-class-tester.c index 2f319e1ed..1f34088c5 100644 --- a/src/Native/GirTestLib/girtest-class-tester.c +++ b/src/Native/GirTestLib/girtest-class-tester.c @@ -34,3 +34,16 @@ girtest_class_tester_transfer_ownership_full_and_unref(GObject *object) { g_object_unref(object); } + +/** + * girtest_class_tester_create_hidden_instance: + * + * Creates a new `girtest_class_tester_new` disguised in a GObject. + * + * Returns: (transfer full): The newly created `girtest_class_tester` casted as GObject. + */ +GObject* +girtest_class_tester_create_hidden_instance (void) +{ + return g_object_new (GIRTEST_TYPE_CLASS_TESTER, NULL); +} \ No newline at end of file diff --git a/src/Native/GirTestLib/girtest-class-tester.h b/src/Native/GirTestLib/girtest-class-tester.h index bc3fb5a82..ec1c97c14 100644 --- a/src/Native/GirTestLib/girtest-class-tester.h +++ b/src/Native/GirTestLib/girtest-class-tester.h @@ -11,5 +11,8 @@ G_DECLARE_FINAL_TYPE(GirTestClassTester, girtest_class_tester, GIRTEST, CLASS_TE void girtest_class_tester_transfer_ownership_full_and_unref(GObject *object); +GObject* +girtest_class_tester_create_hidden_instance (void); + G_END_DECLS diff --git a/src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs b/src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs index 12d6abe00..b1d43af43 100644 --- a/src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs +++ b/src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs @@ -30,6 +30,17 @@ public void InstanceIsGarbageCollectedAfterOwnershipTransferAndUnref() reference.IsAlive.Should().BeFalse(); } + [TestMethod] + public void CanReturnHiddenInstance() + { + //Ensure that return type of "CreateHiddenInstance" is "GObject.Object" + typeof(ClassTester).GetMethod(nameof(ClassTester.CreateHiddenInstance)).Should().Return(); + + //Ensure that returned instance actually is a "ClassTester" + var instance = ClassTester.CreateHiddenInstance(); + instance.Should().BeOfType(); + } + private class TestClass : GObject.Object { public TestClass() : base(true, System.Array.Empty()) { }