gir.core icon indicating copy to clipboard operation
gir.core copied to clipboard

Do not use reflection to create objects from IntPtr but SafeHandles

Open badcel opened this issue 3 years ago • 2 comments

Currently we use reflection to create an object from an IntPtr:

https://github.com/gircore/gir.core/blob/cc0732290999a390478602c51bafaf3650d8d006/Libs/GObject-2.0/Native/Classes/ObjectWrapper.cs#L70

https://github.com/gircore/gir.core/blob/2e2575061fca2cbdc7f359195e59ec7411ed998b/Libs/GObject-2.0/Native/Classes/BoxedWrapper.cs#L59

This is necessary because the TypeDictioanry only returns our instance type for a given GType.

If we update the Native Methods in a way that they return a concrete SafeHandle instead of an IntPtr and each SafeHandle provides a method like CreateInstance this method could create the concrete instance and effectively wrap itself into an object.

Currently only records use SafeHandle. For this to work classes would need to use SafeHandles, too.

One point which is not completely solved with this is that a GValue holding a boxed type can only return an IntPtr and not a SafeHandle ~~In this case we can create the concrete SafeHandle (probably via reflection) and again call CreateInstance~~ Another possibility is that the type dictionary does carry an action which accepts an IntPtr and creates the needed SafeHandle. In This way if one has the GType and an IntPtr one could get the correct action from the type dictioanry and with this the SafeHandle, which itself can create the instance. Thus avoiding reflection alltogether.

There is a special cases for GDK Event. In this case the given type does not correlate to one class, but to many different classes / events. If we can detect this scenario during generation time, we can generate all the needed code in the safe handle. As this code is currently not generated, we need to allow the CreateInstance method of the SafeHandle to be customizeable.

This code should get obsolete with it: https://github.com/gircore/gir.core/blob/395bf92f8d646dd7aff71bd79ba3829b089df5e1/src/Generation/Generator3/Generation/Record/PublicClass/PublicClassTemplate.cs#L36

https://github.com/gircore/gir.core/blob/395bf92f8d646dd7aff71bd79ba3829b089df5e1/src/Libs/GObject-2.0/Internal/Classes/BoxedWrapper.cs#L54

https://github.com/gircore/gir.core/blob/395bf92f8d646dd7aff71bd79ba3829b089df5e1/src/Libs/GObject-2.0/Internal/Classes/BoxedWrapper.cs#L44

Hint: Boxed types have a copy/free function pair, which can be implemented via refcounting

Update: It is not possible to rely on a safe handle which knows the C/C# types as the returned safe handle could be of type „Widget“ but the instance be of type „Button“. It is always necessary to detect the „real“ type of an instance.

badcel avatar Aug 07 '21 17:08 badcel

Using safe handles allows to differentiate between owned and unowned handles. This would simplify the object constructor which currently requires an intptr and the information of the ptr is owned or not as a bool.

badcel avatar Apr 28 '22 07:04 badcel

Alternatively it is possible with dotnet 7 to define a static interface method which creates an instance of an object.

The safehandle on the other hand could carry the information regarding it's GType and dotnet type. Meaning if we have a handle we automatically know it's type in C and dotnet world.

badcel avatar Dec 18 '22 10:12 badcel