summaryrefslogtreecommitdiff
path: root/src/bindings/mono/eo_mono
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-06-28 10:29:01 -0300
committerVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-06-28 10:38:57 -0300
commitb7fa7d48ac9eff4b360e83de4d974a92c84c0291 (patch)
tree91c1ed776686af99a4fb19d816a4f4e5548f84ea /src/bindings/mono/eo_mono
parent549c417853f8f934a8fe63cd0c0cb2d4e8e9ff01 (diff)
csharp: make inherited C# classes constructible from native C
Summary: With this commit it is now possible for a class that inherits from a C# binding class to be instantiated from native C code. It only has to provide a constructor that receives an `Efl.Eo.EoWrapper.ConstructingHandle` struct, and which calls the base binding constructor passing it. For example: `private Type(ConstructingHandle ch) : base(ch) {}`. Add some test files to validate the proper behavior of this feature. Add some small fixes in generation contexts in order to properly generate base constructors. Depends on D9070 Test Plan: `meson test` and `make check` Reviewers: lauromoura, felipealmeida, segfaultxavi, woohyun, YOhoho Reviewed By: YOhoho Subscribers: YOhoho, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9071
Diffstat (limited to 'src/bindings/mono/eo_mono')
-rw-r--r--src/bindings/mono/eo_mono/EoWrapper.cs112
-rw-r--r--src/bindings/mono/eo_mono/iwrapper.cs11
2 files changed, 117 insertions, 6 deletions
diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs
index b6ea619..7e512ac 100644
--- a/src/bindings/mono/eo_mono/EoWrapper.cs
+++ b/src/bindings/mono/eo_mono/EoWrapper.cs
@@ -2,6 +2,7 @@ using System;
2using System.Runtime.InteropServices; 2using System.Runtime.InteropServices;
3using System.Runtime.CompilerServices; 3using System.Runtime.CompilerServices;
4using System.Threading; 4using System.Threading;
5using System.Reflection;
5 6
6namespace Efl 7namespace Efl
7{ 8{
@@ -18,6 +19,33 @@ public abstract class EoWrapper : IWrapper, IDisposable
18 private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback); 19 private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback);
19 private static Efl.EventCb ownershipSharedDelegate = new Efl.EventCb(OwnershipSharedCallback); 20 private static Efl.EventCb ownershipSharedDelegate = new Efl.EventCb(OwnershipSharedCallback);
20 21
22
23 /// <summary>Constructor to be used when objects are expected to be constructed from native code.
24 /// For a class that inherited from an EFL# class to be properly constructed from native code
25 /// one must create a constructor with this signature and calls this base constructor from it.
26 /// This constructor will take care of calling base constructors of the native classes and
27 /// perform additional setup so objects are ready to use.
28 /// It is advisable to check for the <see cref="NativeHandle"/> property in the top level
29 /// constructor and signal an error when it has a value of IntPtr.Zero after this
30 /// constructor completion.
31 /// Warning: Do not use this constructor directly from a `new` statement.</summary>
32 /// <param name="ch">Tag struct storing the native handle of the object being constructed.</param>
33 protected EoWrapper(ConstructingHandle ch)
34 {
35 inherited = true;
36 handle = Efl.Eo.Globals.efl_constructor(Efl.Eo.Globals.efl_super(ch.NativeHandle, Efl.Eo.Globals.efl_class_get(ch.NativeHandle)));
37 if (handle == IntPtr.Zero)
38 {
39 Eina.Log.Warning("Natice constructor returned NULL");
40 return;
41 }
42
43 AddWrapperSupervisor();
44 // Make an additional reference to C#
45 // - Will also call EVENT_OWNERSHIP_SHARED
46 Efl.Eo.Globals.efl_ref(handle);
47 }
48
21 /// <summary>Initializes a new instance of the <see cref="Object"/> class. 49 /// <summary>Initializes a new instance of the <see cref="Object"/> class.
22 /// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary> 50 /// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>
23 /// <param name="raw">The native pointer to be wrapped.</param> 51 /// <param name="raw">The native pointer to be wrapped.</param>
@@ -54,7 +82,17 @@ public abstract class EoWrapper : IWrapper, IDisposable
54 parent_ptr = parent.NativeHandle; 82 parent_ptr = parent.NativeHandle;
55 } 83 }
56 84
57 handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0); 85 if (!inherited)
86 {
87 handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0);
88 }
89 else
90 {
91 handle = Efl.Eo.Globals._efl_add_internal_start_bindings(file, line, actual_klass, parent_ptr, 1, 0,
92 Efl.Eo.Globals.efl_mono_avoid_top_level_constructor_callback_addr_get(),
93 IntPtr.Zero);
94 }
95
58 if (handle == System.IntPtr.Zero) 96 if (handle == System.IntPtr.Zero)
59 { 97 {
60 throw new Exception("Instantiation failed"); 98 throw new Exception("Instantiation failed");
@@ -246,8 +284,78 @@ public abstract class EoWrapper : IWrapper, IDisposable
246 AddNativeEventHandler("eo", "_EFL_EVENT_OWNERSHIP_SHARED", ownershipSharedDelegate, ownershipSharedDelegate); 284 AddNativeEventHandler("eo", "_EFL_EVENT_OWNERSHIP_SHARED", ownershipSharedDelegate, ownershipSharedDelegate);
247 Eina.Error.RaiseIfUnhandledException(); 285 Eina.Error.RaiseIfUnhandledException();
248 } 286 }
287
288 protected struct ConstructingHandle
289 {
290 public ConstructingHandle(IntPtr h)
291 {
292 NativeHandle = h;
293 }
294
295 public IntPtr NativeHandle { get; set; }
296 }
297
298 public abstract class NativeMethods : Efl.Eo.NativeClass
299 {
300 private static EflConstructorDelegate csharpEflConstructorStaticDelegate = new EflConstructorDelegate(Constructor);
301 private static Efl.Eo.NativeModule EoModule = new Efl.Eo.NativeModule("eo");
302
303 private delegate IntPtr EflConstructorDelegate(IntPtr obj, IntPtr pd);
304
305 public override System.Collections.Generic.List<Efl_Op_Description> GetEoOps(Type type)
306 {
307 var descs = new System.Collections.Generic.List<Efl_Op_Description>();
308
309 descs.Add(new Efl_Op_Description()
310 {
311 api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(EoModule.Module, "efl_constructor"),
312 func = Marshal.GetFunctionPointerForDelegate(csharpEflConstructorStaticDelegate)
313 });
314
315 return descs;
316 }
317
318 private static IntPtr Constructor(IntPtr obj, IntPtr pd)
319 {
320 try
321 {
322 var eoKlass = Efl.Eo.Globals.efl_class_get(obj);
323 var managedType = ClassRegister.GetManagedType(eoKlass);
324 if (managedType == null)
325 {
326 IntPtr nativeName = Efl.Eo.Globals.efl_class_name_get(eoKlass);
327 var name = Eina.StringConversion.NativeUtf8ToManagedString(nativeName);
328 Eina.Log.Warning($"Can't get Managed class for object handle 0x{(UInt64)obj:x} with native class [{name}]");
329 return IntPtr.Zero;
330 }
331
332 var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
333 ConstructorInfo constructor = managedType.GetConstructor(flags, null, new Type[1] { typeof(ConstructingHandle) }, null);
334 if (constructor == null)
335 {
336 Eina.Log.Error($"Type {managedType.FullName} lacks a constructor that receives a ConstructingHandle. It can not be constructed from native code.");
337 return IntPtr.Zero;
338 }
339
340 var eoWrapper = (Efl.Eo.IWrapper) constructor.Invoke(new object[1] { new ConstructingHandle(obj) });
341 if (eoWrapper == null)
342 {
343 Eina.Log.Warning("Constructor was unable to create a new object");
344 return IntPtr.Zero;
345 }
346
347 return eoWrapper.NativeHandle;
348 }
349 catch (Exception e)
350 {
351 Eina.Log.Warning($"Inherited constructor error: {e.ToString()}");
352 Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
353 return IntPtr.Zero;
354 }
355 }
356 }
249} 357}
250 358
251} // namespace Global 359} // namespace Eo
252 360
253} // namespace Efl 361} // namespace Efl
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
index 82c08cc..966759b 100644
--- a/src/bindings/mono/eo_mono/iwrapper.cs
+++ b/src/bindings/mono/eo_mono/iwrapper.cs
@@ -44,10 +44,6 @@ public class Globals
44 public static FunctionWrapper<efl_object_shutdown_delegate> efl_object_shutdown_ptr = new FunctionWrapper<efl_object_shutdown_delegate>(efl.Libs.EoModule, "efl_object_shutdown"); 44 public static FunctionWrapper<efl_object_shutdown_delegate> efl_object_shutdown_ptr = new FunctionWrapper<efl_object_shutdown_delegate>(efl.Libs.EoModule, "efl_object_shutdown");
45 public static void efl_object_shutdown() => efl_object_shutdown_ptr.Value.Delegate(); 45 public static void efl_object_shutdown() => efl_object_shutdown_ptr.Value.Delegate();
46 // [DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown(); 46 // [DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown();
47 public static FunctionWrapper<_efl_add_internal_start_delegate> _efl_add_internal_start_ptr = new FunctionWrapper<_efl_add_internal_start_delegate>(efl.Libs.EoModule, "_efl_add_internal_start");
48 public delegate IntPtr
49 _efl_add_internal_start_delegate([MarshalAs(UnmanagedType.LPStr)] String file, int line,
50 IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
51 47
52 [DllImport(efl.Libs.CustomExports)] public static extern IntPtr efl_mono_wrapper_supervisor_get(IntPtr eo); 48 [DllImport(efl.Libs.CustomExports)] public static extern IntPtr efl_mono_wrapper_supervisor_get(IntPtr eo);
53 [DllImport(efl.Libs.CustomExports)] public static extern void efl_mono_wrapper_supervisor_set(IntPtr eo, IntPtr ws); 49 [DllImport(efl.Libs.CustomExports)] public static extern void efl_mono_wrapper_supervisor_set(IntPtr eo, IntPtr ws);
@@ -55,6 +51,9 @@ public class Globals
55 [DllImport(efl.Libs.Eo)] public static extern IntPtr 51 [DllImport(efl.Libs.Eo)] public static extern IntPtr
56 _efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line, 52 _efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line,
57 IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback); 53 IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
54 [DllImport(efl.Libs.Eo)] public static extern IntPtr
55 _efl_add_internal_start_bindings([MarshalAs(UnmanagedType.LPStr)] String file, int line, IntPtr klass, IntPtr parent,
56 byte is_ref, byte is_fallback, IntPtr substitute_ctor, IntPtr data);
58 public delegate IntPtr 57 public delegate IntPtr
59 _efl_add_end_delegate(IntPtr eo, byte is_ref, byte is_fallback); 58 _efl_add_end_delegate(IntPtr eo, byte is_ref, byte is_fallback);
60 [DllImport(efl.Libs.Eo)] public static extern IntPtr 59 [DllImport(efl.Libs.Eo)] public static extern IntPtr
@@ -196,6 +195,10 @@ public class Globals
196 public delegate IntPtr dlerror_delegate(); 195 public delegate IntPtr dlerror_delegate();
197 [DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror(); 196 [DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
198 197
198 [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_constructor(IntPtr obj);
199
200 [DllImport(efl.Libs.CustomExports)] public static extern IntPtr efl_mono_avoid_top_level_constructor_callback_addr_get();
201
199 [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool 202 [DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
200 efl_event_callback_priority_add(IntPtr obj, IntPtr desc, short priority, IntPtr cb, IntPtr data); 203 efl_event_callback_priority_add(IntPtr obj, IntPtr desc, short priority, IntPtr cb, IntPtr data);
201 204