Skip to content

Commit

Permalink
Avoid marshalling of instance data
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel committed Jan 20, 2024
1 parent 7e5a865 commit f98b667
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 7 deletions.
13 changes: 6 additions & 7 deletions src/Libs/GObject-2.0/Internal/ObjectWrapper.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -78,16 +78,15 @@ public static T WrapInterfaceHandle<T>(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<TypeInstanceData>(handle);
TypeClassData klass = Marshal.PtrToStructure<TypeClassData>(instance.GClass);
var typeid = klass.GType;
var gclass = Unsafe.AsRef<TypeInstanceData>((void*) handle).GClass;
var gtype = Unsafe.AsRef<TypeClassData>((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)
Expand Down
13 changes: 13 additions & 0 deletions src/Native/GirTestLib/girtest-class-tester.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
3 changes: 3 additions & 0 deletions src/Native/GirTestLib/girtest-class-tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

11 changes: 11 additions & 0 deletions src/Tests/Libs/GirTest-0.1.Tests/ClassTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<GObject.Object>();

//Ensure that returned instance actually is a "ClassTester"
var instance = ClassTester.CreateHiddenInstance();
instance.Should().BeOfType<ClassTester>();
}

private class TestClass : GObject.Object
{
public TestClass() : base(true, System.Array.Empty<GObject.ConstructArgument>()) { }
Expand Down

0 comments on commit f98b667

Please sign in to comment.