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 << scope_tab << "add\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 << scope_tab << "Efl.EventCb callerCb = (IntPtr data, ref Efl.Event.NativeStruct evt) =>\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 << "remove\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 << scope_tab << "string key = \"_" << upper_c_name << "\";\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";
// 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)
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)
self = "";

View File

@ -214,7 +214,7 @@ struct klass
<< 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 << "/// 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\n"
)
@ -511,7 +511,7 @@ struct klass
<< 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 << "/// <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\n"
).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
@ -526,7 +526,7 @@ struct klass
scope_tab << "[Efl.Eo.PrivateNativeClass]\n"
<< scope_tab << "private class " << inherit_name << "Realized : " << inherit_name << "\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 << "}\n"

View File

@ -12,9 +12,9 @@ namespace Eo
public abstract class EoWrapper : IWrapper, IDisposable
{
protected readonly object eventLock = new object();
protected bool inherited = false;
protected System.IntPtr handle = IntPtr.Zero;
protected readonly object eflBindingEventLock = new object();
private bool generated = true;
private System.IntPtr handle = IntPtr.Zero;
private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback);
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>
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)));
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.
/// 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>
protected EoWrapper(System.IntPtr raw)
protected EoWrapper(Efl.Eo.Globals.WrappingHandle wh)
{
handle = raw;
handle = wh.NativeHandle;
AddWrapperSupervisor();
}
@ -67,9 +68,9 @@ public abstract class EoWrapper : IWrapper, IDisposable
[CallerFilePath] string file = null,
[CallerLineNumber] int line = 0)
{
inherited = ((object)this).GetType() != managedType;
generated = ((object)this).GetType() == managedType;
IntPtr actual_klass = baseKlass;
if (inherited)
if (!generated)
{
actual_klass = Efl.Eo.ClassRegister.GetInheritKlassOrRegister(baseKlass, ((object)this).GetType());
}
@ -82,7 +83,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
parent_ptr = parent.NativeHandle;
}
if (!inherited)
if (generated)
{
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;
}
protected bool IsGeneratedBindingClass
{
get { return generated; }
}
/// <summary>Releases the underlying native instance.</summary>
protected virtual void Dispose(bool disposing)
{
@ -292,7 +298,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
NativeHandle = h;
}
public IntPtr NativeHandle { get; set; }
public IntPtr NativeHandle { get; private set; }
}
public abstract class NativeMethods : Efl.Eo.NativeClass

View File

@ -624,14 +624,15 @@ public class Globals
try
{
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)
{
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)
{
@ -715,6 +716,21 @@ public class Globals
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
public static class Config

View File

@ -27,9 +27,10 @@ class InheritedConstructibleObject : Dummy.ConstructibleObject
public int DefaultConstrutorCallCount { 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)
@ -56,7 +57,7 @@ class TestEoConstruction
public static void TestInheritedEoDirectConstruction()
{
var obj = new InheritedConstructibleObject();
Test.AssertEquals(obj.InheritedFlag, true);
Test.AssertEquals(obj.IsInheritedClass, true);
Test.AssertEquals(obj.NativeConstructionCount, 1);
Test.AssertEquals(obj.DefaultConstructionCount, 1);
Test.AssertEquals(obj.SpecialConstructionCount, 0);
@ -75,7 +76,7 @@ class TestEoConstruction
Test.AssertEquals(obj.MultiplyIntegerValue(21), 42);
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.DefaultConstructionCount, 0);
Test.AssertEquals(obj2.SpecialConstructionCount, 1);