csharp: encapsulate some internal code of EoWrapper

Summary:
Encapsulate some parts of EoWrapper making them less accessible to lib users.
This can avoid unnecessary and risky usage of code that is only intended for
internal usage.

`inherited` field was made private and renamed to `generated`. Now its value
can only be obtained through the `IsGeneratedBindingClass` property.

`handle` field was made private.

`eventLock` was renamed to `eflBindingEventLock`

`ConstructingHandle` property set was made private.

Constructors that are used to create new EFL# managed objects by wrapping a
preexisting eo handle now receive a specific struct wrapping the handle pointer.
This can avoid faulty interactions with the Reflection engine used only for
generated classes that implement this constructor.

Test Plan: meson test

Reviewers: lauromoura, felipealmeida, YOhoho

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D9212
This commit is contained in:
Vitor Sousa 2019-06-28 18:20:01 -03:00 committed by Jaehyun-Cho
parent a94c72f4de
commit 73df0d47ff
6 changed files with 48 additions and 24 deletions

View File

@ -435,7 +435,7 @@ struct event_definition_generator
scope_tab << "{\n" scope_tab << "{\n"
<< scope_tab << scope_tab << "add\n" << scope_tab << scope_tab << "add\n"
<< scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << "lock (eventLock)\n" << scope_tab << scope_tab << scope_tab << "lock (eflBindingEventLock)\n"
<< scope_tab << scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "Efl.EventCb callerCb = (IntPtr data, ref Efl.Event.NativeStruct evt) =>\n" << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.EventCb callerCb = (IntPtr data, ref Efl.Event.NativeStruct evt) =>\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << scope_tab << scope_tab << "{\n"
@ -460,7 +460,7 @@ struct event_definition_generator
<< scope_tab << scope_tab << "}\n\n" << scope_tab << scope_tab << "}\n\n"
<< scope_tab << scope_tab << "remove\n" << scope_tab << scope_tab << "remove\n"
<< scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << "lock (eventLock)\n" << scope_tab << scope_tab << scope_tab << "lock (eflBindingEventLock)\n"
<< scope_tab << scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n" << scope_tab << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
<< scope_tab << scope_tab << scope_tab << scope_tab << "RemoveNativeEventHandler(" << library_name << ", key, value);\n" << scope_tab << scope_tab << scope_tab << scope_tab << "RemoveNativeEventHandler(" << library_name << ", key, value);\n"

View File

@ -178,9 +178,10 @@ struct function_definition_generator
std::string self = "this.NativeHandle"; std::string self = "this.NativeHandle";
// inherited is set in the constructor, true if this instance is from a pure C# class (not generated). // IsGeneratedBindingClass is set in the constructor, true if this
// instance is from a pure C# class (not generated).
if (do_super && !f.is_static) if (do_super && !f.is_static)
self = "(inherited ? Efl.Eo.Globals.efl_super(" + self + ", this.NativeClass) : " + self + ")"; self = "(IsGeneratedBindingClass ? " + self + " : Efl.Eo.Globals.efl_super(" + self + ", this.NativeClass))";
else if (f.is_static) else if (f.is_static)
self = ""; self = "";

View File

@ -214,7 +214,7 @@ struct klass
<< scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n" << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
<< scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << interface_name << "\"/> class.\n" << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << interface_name << "\"/> class.\n"
<< scope_tab << "/// Internal usage: This is used when interacting with C code and should not be used directly.</summary>\n" << scope_tab << "/// Internal usage: This is used when interacting with C code and should not be used directly.</summary>\n"
<< scope_tab << "private " << concrete_name << "(System.IntPtr raw) : base(raw)\n" << scope_tab << "private " << concrete_name << "(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n"
<< scope_tab << "{\n" << scope_tab << "{\n"
<< scope_tab << "}\n\n" << scope_tab << "}\n\n"
) )
@ -511,7 +511,7 @@ struct klass
<< scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n" << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
<< scope_tab << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n" << scope_tab << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
<< scope_tab << "/// <param name=\"raw\">The native pointer to be wrapped.</param>\n" << scope_tab << "/// <param name=\"raw\">The native pointer to be wrapped.</param>\n"
<< scope_tab << "protected " << inherit_name << "(System.IntPtr raw) : base(raw)\n" << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n"
<< scope_tab << "{\n" << scope_tab << "{\n"
<< scope_tab << "}\n\n" << scope_tab << "}\n\n"
).generate(sink, std::make_tuple(constructors, constructors, constructors), context)) ).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
@ -526,7 +526,7 @@ struct klass
scope_tab << "[Efl.Eo.PrivateNativeClass]\n" scope_tab << "[Efl.Eo.PrivateNativeClass]\n"
<< scope_tab << "private class " << inherit_name << "Realized : " << inherit_name << "\n" << scope_tab << "private class " << inherit_name << "Realized : " << inherit_name << "\n"
<< scope_tab << "{\n" << scope_tab << "{\n"
<< scope_tab << scope_tab << "private " << inherit_name << "Realized(IntPtr ptr) : base(ptr)\n" << scope_tab << scope_tab << "private " << inherit_name << "Realized(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n"
<< scope_tab << scope_tab << "{\n" << scope_tab << scope_tab << "{\n"
<< scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << "}\n"
<< scope_tab << "}\n" << scope_tab << "}\n"

View File

@ -12,9 +12,9 @@ namespace Eo
public abstract class EoWrapper : IWrapper, IDisposable public abstract class EoWrapper : IWrapper, IDisposable
{ {
protected readonly object eventLock = new object(); protected readonly object eflBindingEventLock = new object();
protected bool inherited = false; private bool generated = true;
protected System.IntPtr handle = IntPtr.Zero; private System.IntPtr handle = IntPtr.Zero;
private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback); private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback);
private static Efl.EventCb ownershipSharedDelegate = new Efl.EventCb(OwnershipSharedCallback); private static Efl.EventCb ownershipSharedDelegate = new Efl.EventCb(OwnershipSharedCallback);
@ -32,7 +32,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
/// <param name="ch">Tag struct storing the native handle of the object being constructed.</param> /// <param name="ch">Tag struct storing the native handle of the object being constructed.</param>
protected EoWrapper(ConstructingHandle ch) protected EoWrapper(ConstructingHandle ch)
{ {
inherited = true; generated = false;
handle = Efl.Eo.Globals.efl_constructor(Efl.Eo.Globals.efl_super(ch.NativeHandle, Efl.Eo.Globals.efl_class_get(ch.NativeHandle))); handle = Efl.Eo.Globals.efl_constructor(Efl.Eo.Globals.efl_super(ch.NativeHandle, Efl.Eo.Globals.efl_class_get(ch.NativeHandle)));
if (handle == IntPtr.Zero) if (handle == IntPtr.Zero)
{ {
@ -47,11 +47,12 @@ public abstract class EoWrapper : IWrapper, IDisposable
} }
/// <summary>Initializes a new instance of the <see cref="Object"/> class. /// <summary>Initializes a new instance of the <see cref="Object"/> class.
/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary> /// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.
/// Do not implement this constructor.</summary>
/// <param name="raw">The native pointer to be wrapped.</param> /// <param name="raw">The native pointer to be wrapped.</param>
protected EoWrapper(System.IntPtr raw) protected EoWrapper(Efl.Eo.Globals.WrappingHandle wh)
{ {
handle = raw; handle = wh.NativeHandle;
AddWrapperSupervisor(); AddWrapperSupervisor();
} }
@ -67,9 +68,9 @@ public abstract class EoWrapper : IWrapper, IDisposable
[CallerFilePath] string file = null, [CallerFilePath] string file = null,
[CallerLineNumber] int line = 0) [CallerLineNumber] int line = 0)
{ {
inherited = ((object)this).GetType() != managedType; generated = ((object)this).GetType() == managedType;
IntPtr actual_klass = baseKlass; IntPtr actual_klass = baseKlass;
if (inherited) if (!generated)
{ {
actual_klass = Efl.Eo.ClassRegister.GetInheritKlassOrRegister(baseKlass, ((object)this).GetType()); actual_klass = Efl.Eo.ClassRegister.GetInheritKlassOrRegister(baseKlass, ((object)this).GetType());
} }
@ -82,7 +83,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
parent_ptr = parent.NativeHandle; parent_ptr = parent.NativeHandle;
} }
if (!inherited) if (generated)
{ {
handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0); handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0);
} }
@ -123,6 +124,11 @@ public abstract class EoWrapper : IWrapper, IDisposable
get; get;
} }
protected bool IsGeneratedBindingClass
{
get { return generated; }
}
/// <summary>Releases the underlying native instance.</summary> /// <summary>Releases the underlying native instance.</summary>
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
@ -292,7 +298,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
NativeHandle = h; NativeHandle = h;
} }
public IntPtr NativeHandle { get; set; } public IntPtr NativeHandle { get; private set; }
} }
public abstract class NativeMethods : Efl.Eo.NativeClass public abstract class NativeMethods : Efl.Eo.NativeClass

View File

@ -624,14 +624,15 @@ public class Globals
try try
{ {
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
constructor = managedType.GetConstructor(flags, null, new Type[1] { typeof(System.IntPtr) }, null); constructor = managedType.GetConstructor(flags, null, new Type[1] { typeof(WrappingHandle) }, null);
} }
catch (InvalidOperationException) catch (InvalidOperationException)
{ {
throw new InvalidOperationException($"Can't get constructor for type {managedType}"); throw new InvalidOperationException($"Can't get constructor for type {managedType}");
} }
var ret = (Efl.Eo.IWrapper) constructor.Invoke(new object[1] { handle }); WrappingHandle wh = new WrappingHandle(handle);
var ret = (Efl.Eo.IWrapper) constructor.Invoke(new object[1] { wh });
if (ret == null) if (ret == null)
{ {
@ -715,6 +716,21 @@ public class Globals
Monitor.Exit(Efl.All.InitLock); Monitor.Exit(Efl.All.InitLock);
} }
/// <sumary>
/// Internal struct used by the binding to pass the native handle pointer
/// to the managed object wrapping constructor.
/// Internal usage only: do not use this class in inherited classes.
/// </sumary>
public struct WrappingHandle
{
public WrappingHandle(IntPtr h)
{
NativeHandle = h;
}
public IntPtr NativeHandle { get; private set; }
}
} // Globals } // Globals
public static class Config public static class Config

View File

@ -27,9 +27,10 @@ class InheritedConstructibleObject : Dummy.ConstructibleObject
public int DefaultConstrutorCallCount { get; set; } = 0; public int DefaultConstrutorCallCount { get; set; } = 0;
public int SpecialConstrutorCallCount { get; set; } = 0; public int SpecialConstrutorCallCount { get; set; } = 0;
public bool InheritedFlag /// <summary>Pointer to the native class description.</summary>
public bool IsInheritedClass
{ {
get { return inherited; } get { return !this.IsGeneratedBindingClass; }
} }
public override int MultiplyIntegerValue(int v) public override int MultiplyIntegerValue(int v)
@ -56,7 +57,7 @@ class TestEoConstruction
public static void TestInheritedEoDirectConstruction() public static void TestInheritedEoDirectConstruction()
{ {
var obj = new InheritedConstructibleObject(); var obj = new InheritedConstructibleObject();
Test.AssertEquals(obj.InheritedFlag, true); Test.AssertEquals(obj.IsInheritedClass, true);
Test.AssertEquals(obj.NativeConstructionCount, 1); Test.AssertEquals(obj.NativeConstructionCount, 1);
Test.AssertEquals(obj.DefaultConstructionCount, 1); Test.AssertEquals(obj.DefaultConstructionCount, 1);
Test.AssertEquals(obj.SpecialConstructionCount, 0); Test.AssertEquals(obj.SpecialConstructionCount, 0);
@ -75,7 +76,7 @@ class TestEoConstruction
Test.AssertEquals(obj.MultiplyIntegerValue(21), 42); Test.AssertEquals(obj.MultiplyIntegerValue(21), 42);
var obj2 = (InheritedConstructibleObject) obj.ConstructTypeAndStore(typeof(InheritedConstructibleObject)); var obj2 = (InheritedConstructibleObject) obj.ConstructTypeAndStore(typeof(InheritedConstructibleObject));
Test.AssertEquals(obj2.InheritedFlag, true); Test.AssertEquals(obj2.IsInheritedClass, true);
Test.AssertEquals(obj2.NativeConstructionCount, 1); Test.AssertEquals(obj2.NativeConstructionCount, 1);
Test.AssertEquals(obj2.DefaultConstructionCount, 0); Test.AssertEquals(obj2.DefaultConstructionCount, 0);
Test.AssertEquals(obj2.SpecialConstructionCount, 1); Test.AssertEquals(obj2.SpecialConstructionCount, 1);