forked from enlightenment/efl
efl-mono: Add support for Efl.Class
Efl.Class (in practice, the return from the *_class_get() functions) can be used as argument to functions, like in Efl.Object.provider_find and Efl.Ui.Widget_Factory.item_class(get/set). This commits adds support by representing Efl.Class instances as System.Type in the C# API, allowing someone to do things like: `factory.ItemClass == typeof(MyFramework.MyButton)` It also supports user-defined classes that inherit from efl classes.
This commit is contained in:
parent
6d61ca9151
commit
dd89eb2fd1
|
@ -347,6 +347,15 @@ struct klass
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copied from nativeinherit class, used when setting up providers.
|
||||||
|
if(!as_generator(
|
||||||
|
scope_tab << "private static " << (root ? "" : "new ") << " IntPtr GetEflClassStatic()\n"
|
||||||
|
<< scope_tab << "{\n"
|
||||||
|
<< scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
|
||||||
|
<< scope_tab << "}\n"
|
||||||
|
).generate(sink, attributes::unused, inherit_cxt))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
|
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +463,7 @@ struct klass
|
||||||
<< scope_tab << scope_tab << scope_tab << "if (((object)this).GetType() == typeof (" << inherit_name << "))\n"
|
<< scope_tab << scope_tab << scope_tab << "if (((object)this).GetType() == typeof (" << inherit_name << "))\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "return " << native_inherit_full_name << ".GetEflClassStatic();\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "return " << native_inherit_full_name << ".GetEflClassStatic();\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "else\n"
|
<< scope_tab << scope_tab << scope_tab << "else\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "return Efl.Eo.Globals.klasses[((object)this).GetType()];\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "return Efl.Eo.ClassRegister.klassFromType[((object)this).GetType()];\n"
|
||||||
<< scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << "}\n"
|
<< scope_tab << "}\n"
|
||||||
).generate(sink, attributes::unused, context))
|
).generate(sink, attributes::unused, context))
|
||||||
|
@ -512,7 +521,7 @@ struct klass
|
||||||
// For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
|
// For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
|
||||||
<< scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n"
|
<< scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") :\n"
|
<< scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") :\n"
|
||||||
<< scope_tab << scope_tab << (root ? "this" : "base") << "(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
|
<< scope_tab << scope_tab << (root ? "this" : "base") << "(" << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< *(scope_tab << scope_tab << constructor_invocation << "\n" )
|
<< *(scope_tab << scope_tab << constructor_invocation << "\n" )
|
||||||
<< scope_tab << scope_tab << "FinishInstantiation();\n"
|
<< scope_tab << scope_tab << "FinishInstantiation();\n"
|
||||||
|
@ -531,7 +540,7 @@ struct klass
|
||||||
{
|
{
|
||||||
return as_generator(
|
return as_generator(
|
||||||
scope_tab << "///<summary>Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.</summary>\n"
|
scope_tab << "///<summary>Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.</summary>\n"
|
||||||
<< scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n"
|
<< scope_tab << "protected " << inherit_name << "(IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(base_klass, managed_type, parent) {}\n"
|
||||||
).generate(sink, attributes::unused, context);
|
).generate(sink, attributes::unused, context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -539,22 +548,12 @@ struct klass
|
||||||
// Detailed constructors go only in root classes.
|
// Detailed constructors go only in root classes.
|
||||||
return as_generator(
|
return as_generator(
|
||||||
/// Actual root costructor that creates class and instantiates
|
/// Actual root costructor that creates class and instantiates
|
||||||
scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
|
scope_tab << "protected " << inherit_name << "(IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n"
|
<< scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n"
|
||||||
<< scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
|
<< scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
|
||||||
<< scope_tab << scope_tab << "if (inherited) {\n"
|
<< scope_tab << scope_tab << "if (inherited) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "if (!Efl.Eo.Globals.klasses.ContainsKey(((object)this).GetType())) {\n"
|
<< scope_tab << scope_tab << scope_tab << "actual_klass = Efl.Eo.ClassRegister.GetInheritKlassOrRegister(base_klass, ((object)this).GetType());\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "actual_klass = Efl.Eo.Globals.register_class(klass_name, base_klass, ((object)this).GetType());\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (actual_klass == System.IntPtr.Zero) {\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "throw new System.InvalidOperationException(\"Failed to initialize class '" << inherit_name << "'\");\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.klasses[((object)this).GetType()] = actual_klass;\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << "}\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << "else\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "actual_klass = Efl.Eo.Globals.klasses[((object)this).GetType()];\n"
|
|
||||||
<< scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << "handle = Efl.Eo.Globals.instantiate_start(actual_klass, parent);\n"
|
<< scope_tab << scope_tab << "handle = Efl.Eo.Globals.instantiate_start(actual_klass, parent);\n"
|
||||||
<< scope_tab << scope_tab << "register_event_proxies();\n"
|
<< scope_tab << scope_tab << "register_event_proxies();\n"
|
||||||
|
|
|
@ -142,12 +142,22 @@ struct marshall_annotation_visitor_generate
|
||||||
}
|
}
|
||||||
bool operator()(attributes::klass_name const& klass_name) const
|
bool operator()(attributes::klass_name const& klass_name) const
|
||||||
{
|
{
|
||||||
const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
|
const char *return_prefix = is_return ? "return:" : "";
|
||||||
const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
|
const char *marshal_prefix = "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(";
|
||||||
return as_generator
|
|
||||||
((is_return ? return_prefix : no_return_prefix)
|
std::string name = name_helpers::klass_full_concrete_name(klass_name);
|
||||||
<< string << ", Efl.Eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
|
|
||||||
).generate(sink, name_helpers::klass_full_concrete_name(klass_name), *context);
|
if (name == "Efl.Class")
|
||||||
|
name = "Efl.Eo.MarshalEflClass";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag";
|
||||||
|
name = "Efl.Eo.MarshalTest<" + name + ", Efl.Eo." + own + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
return as_generator(
|
||||||
|
lit("[") << return_prefix << marshal_prefix << name << "))]"
|
||||||
|
).generate(sink, name, *context);
|
||||||
}
|
}
|
||||||
bool operator()(attributes::complex_type_def const& c) const
|
bool operator()(attributes::complex_type_def const& c) const
|
||||||
{
|
{
|
||||||
|
@ -252,12 +262,22 @@ struct marshall_native_annotation_visitor_generate
|
||||||
}
|
}
|
||||||
bool operator()(attributes::klass_name const& klass_name) const
|
bool operator()(attributes::klass_name const& klass_name) const
|
||||||
{
|
{
|
||||||
const char no_return_prefix[] = "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
|
const char *return_prefix = is_return ? "return:" : "";
|
||||||
const char return_prefix[] = "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Efl.Eo.MarshalTest<";
|
const char *marshal_prefix = "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(";
|
||||||
return as_generator
|
|
||||||
((is_return ? return_prefix : no_return_prefix)
|
std::string name = name_helpers::klass_full_concrete_name(klass_name);
|
||||||
<< string << ", Efl.Eo." << (klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag") << ">))]"
|
|
||||||
).generate(sink, name_helpers::klass_full_concrete_name(klass_name), *context);
|
if (name == "Efl.Class")
|
||||||
|
name = "Efl.Eo.MarshalEflClass";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag";
|
||||||
|
name = "Efl.Eo.MarshalTest<" + name + ", Efl.Eo." + own + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
return as_generator(
|
||||||
|
lit("[") << return_prefix << marshal_prefix << name << "))]"
|
||||||
|
).generate(sink, name, *context);
|
||||||
}
|
}
|
||||||
bool operator()(attributes::complex_type_def const& c) const
|
bool operator()(attributes::complex_type_def const& c) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -309,6 +309,9 @@ struct visitor_generate
|
||||||
}
|
}
|
||||||
bool operator()(attributes::klass_name klass) const
|
bool operator()(attributes::klass_name klass) const
|
||||||
{
|
{
|
||||||
|
// Efl.Class is manually handled in a custom marshall to be represented by a System.Type.
|
||||||
|
if (name_helpers::klass_full_concrete_name(klass) == "Efl.Class")
|
||||||
|
return as_generator(lit("Type")).generate(sink, attributes::unused, *context);
|
||||||
if(klass.type == attributes::class_type::regular || klass.type == attributes::class_type::abstract_)
|
if(klass.type == attributes::class_type::regular || klass.type == attributes::class_type::abstract_)
|
||||||
return as_generator(string).generate(sink, name_helpers::klass_full_concrete_name(klass), *context);
|
return as_generator(string).generate(sink, name_helpers::klass_full_concrete_name(klass), *context);
|
||||||
else
|
else
|
||||||
|
|
|
@ -530,23 +530,11 @@ public static class TraitFunctions
|
||||||
|
|
||||||
if (type.IsInterface)
|
if (type.IsInterface)
|
||||||
{
|
{
|
||||||
string[] names = type.FullName.Split('.');
|
string fullName = type.FullName + "Concrete";
|
||||||
names[names.Count() - 1] = names.Last().Substring(1); // Remove the leading 'I' (What about user-defined interfaces?)
|
|
||||||
|
|
||||||
string fullName = string.Join(".", names);
|
|
||||||
return type.Assembly.GetType(fullName); // That was our best guess...
|
return type.Assembly.GetType(fullName); // That was our best guess...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return type; // Not interface, so it should be a concrete.
|
||||||
System.Type current = type;
|
|
||||||
while (current != null)
|
|
||||||
{
|
|
||||||
if (current.Name.EndsWith("Inherit"))
|
|
||||||
throw new Exception("Inherit-based classes are not currently supported.");
|
|
||||||
current = current.BaseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return type; // Not inherited neither interface, so it should be a concrete.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object RegisterTypeTraits<T>()
|
public static object RegisterTypeTraits<T>()
|
||||||
|
|
|
@ -25,6 +25,8 @@ public class Globals {
|
||||||
efl_unref(IntPtr eo);
|
efl_unref(IntPtr eo);
|
||||||
[DllImport(efl.Libs.Eo)] public static extern int
|
[DllImport(efl.Libs.Eo)] public static extern int
|
||||||
efl_ref_count(IntPtr eo);
|
efl_ref_count(IntPtr eo);
|
||||||
|
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
||||||
|
efl_class_name_get(IntPtr eo);
|
||||||
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
||||||
efl_class_new(IntPtr class_description, IntPtr parent, IntPtr term);
|
efl_class_new(IntPtr class_description, IntPtr parent, IntPtr term);
|
||||||
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
||||||
|
@ -150,9 +152,6 @@ public class Globals {
|
||||||
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
[DllImport(efl.Libs.Eo)] public static extern IntPtr
|
||||||
efl_object_legacy_only_event_description_get([MarshalAs(UnmanagedType.LPStr)] String name);
|
efl_object_legacy_only_event_description_get([MarshalAs(UnmanagedType.LPStr)] String name);
|
||||||
|
|
||||||
public static System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr> klasses
|
|
||||||
= new System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr>();
|
|
||||||
|
|
||||||
public const int RTLD_NOW = 2;
|
public const int RTLD_NOW = 2;
|
||||||
|
|
||||||
public delegate byte class_initializer(IntPtr klass);
|
public delegate byte class_initializer(IntPtr klass);
|
||||||
|
@ -529,6 +528,120 @@ public interface IWrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ClassRegister
|
||||||
|
{
|
||||||
|
public static System.Type GetManagedType(IntPtr klass)
|
||||||
|
{
|
||||||
|
System.Type t;
|
||||||
|
if (Efl.Eo.ClassRegister.typeFromKlass.TryGetValue(klass, out t))
|
||||||
|
return t;
|
||||||
|
|
||||||
|
// If it isn't on the dictionary then it is a Native binding class
|
||||||
|
IntPtr namePtr = Efl.Eo.Globals.efl_class_name_get(klass);
|
||||||
|
if (namePtr == IntPtr.Zero) {
|
||||||
|
throw new System.InvalidOperationException($"Could not get Native class name. Handle: {klass}");
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = Eina.StringConversion.NativeUtf8ToManagedString(namePtr)
|
||||||
|
.Replace("_", ""); // Convert Efl C name to C# name
|
||||||
|
|
||||||
|
var curr_asm = typeof(IWrapper).Assembly;
|
||||||
|
t = curr_asm.GetType(name);
|
||||||
|
if (t == null)
|
||||||
|
{
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
if (assembly == curr_asm)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
t = assembly.GetType(name);
|
||||||
|
if (t != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (t == null) {
|
||||||
|
throw new System.InvalidOperationException($"Could not find the C# binding class for the EFL class: {name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddToKlassTypeBiDictionary(klass, t); // Cache it in the dictionary
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetKlass(System.Type objectType)
|
||||||
|
{
|
||||||
|
IntPtr klass;
|
||||||
|
if (klassFromType.TryGetValue(objectType, out klass))
|
||||||
|
return klass;
|
||||||
|
|
||||||
|
// Check if it is a Native binding class
|
||||||
|
klass = GetNativeKlassPtr(objectType);
|
||||||
|
if (klass != IntPtr.Zero) {
|
||||||
|
// Add to the dictionary cache
|
||||||
|
AddToKlassTypeBiDictionary(klass, objectType);
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregistered Inherited class, let's register it
|
||||||
|
IntPtr baseKlass = GetNativeBaseKlassPtr(objectType);
|
||||||
|
if (baseKlass == IntPtr.Zero)
|
||||||
|
throw new System.InvalidOperationException($"Could not get base C# binding class for Inherited type: {objectType.FullName}");
|
||||||
|
return RegisterKlass(baseKlass, objectType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPtr GetInheritKlassOrRegister(IntPtr baseKlass, System.Type objectType)
|
||||||
|
{
|
||||||
|
IntPtr klass;
|
||||||
|
if (klassFromType.TryGetValue(objectType, out klass))
|
||||||
|
return klass;
|
||||||
|
|
||||||
|
return RegisterKlass(baseKlass, objectType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr RegisterKlass(IntPtr baseKlass, System.Type objectType)
|
||||||
|
{
|
||||||
|
lock (klassAllocLock) {
|
||||||
|
IntPtr newKlass = Efl.Eo.Globals.register_class(objectType.FullName, baseKlass, objectType);
|
||||||
|
if (newKlass == IntPtr.Zero) {
|
||||||
|
throw new System.InvalidOperationException($"Failed to register class '{objectType.FullName}'");
|
||||||
|
}
|
||||||
|
AddToKlassTypeBiDictionary(newKlass, objectType);
|
||||||
|
return newKlass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr GetNativeBaseKlassPtr(System.Type objectType)
|
||||||
|
{
|
||||||
|
for (System.Type t = objectType.BaseType; t != null; t = t.BaseType)
|
||||||
|
{
|
||||||
|
var method = t.GetMethod("GetEflClassStatic",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
if (method != null)
|
||||||
|
return (IntPtr) method.Invoke(null, null);
|
||||||
|
}
|
||||||
|
throw new System.InvalidOperationException($"Class '{objectType.FullName}' is not an Efl object");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr GetNativeKlassPtr(System.Type objectType)
|
||||||
|
{
|
||||||
|
var method = objectType.GetMethod("GetEflClassStatic",
|
||||||
|
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
|
||||||
|
return (IntPtr) method?.Invoke(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddToKlassTypeBiDictionary(IntPtr klassPtr, System.Type objectType)
|
||||||
|
{
|
||||||
|
klassFromType[objectType] = klassPtr;
|
||||||
|
typeFromKlass[klassPtr] = objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr> klassFromType
|
||||||
|
= new System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr>();
|
||||||
|
|
||||||
|
public static System.Collections.Concurrent.ConcurrentDictionary<System.IntPtr, System.Type> typeFromKlass
|
||||||
|
= new System.Collections.Concurrent.ConcurrentDictionary<System.IntPtr, System.Type>();
|
||||||
|
|
||||||
|
private static readonly object klassAllocLock = new object();
|
||||||
|
}
|
||||||
|
|
||||||
public interface IOwnershipTag
|
public interface IOwnershipTag
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -587,6 +700,46 @@ public class MarshalTest<T, U> : ICustomMarshaler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///<summary>Marshals between System.Type instances and Eo classes (IntPtrs).</summary>
|
||||||
|
public class MarshalEflClass : ICustomMarshaler
|
||||||
|
{
|
||||||
|
public static ICustomMarshaler GetInstance(string cookie)
|
||||||
|
{
|
||||||
|
Eina.Log.Debug("MarshalTest.GetInstance cookie " + cookie);
|
||||||
|
return new MarshalEflClass();
|
||||||
|
}
|
||||||
|
public void CleanUpManagedData(object ManagedObj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanUpNativeData(IntPtr pNativeData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetNativeDataSize()
|
||||||
|
{
|
||||||
|
Eina.Log.Debug("MarshalTest.GetNativeDataSize");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntPtr MarshalManagedToNative(object ManagedObj)
|
||||||
|
{
|
||||||
|
Eina.Log.Debug("MarshalTest.MarshallManagedToNative");
|
||||||
|
if (ManagedObj == null)
|
||||||
|
return IntPtr.Zero;
|
||||||
|
var t = (System.Type) ManagedObj;
|
||||||
|
return Efl.Eo.ClassRegister.GetKlass(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||||
|
{
|
||||||
|
Eina.Log.Debug("MarshalTest.MarshalNativeToManaged");
|
||||||
|
if (pNativeData == IntPtr.Zero)
|
||||||
|
return null;
|
||||||
|
return Efl.Eo.ClassRegister.GetManagedType(pNativeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class StringPassOwnershipMarshaler : ICustomMarshaler {
|
public class StringPassOwnershipMarshaler : ICustomMarshaler {
|
||||||
public object MarshalNativeToManaged(IntPtr pNativeData) {
|
public object MarshalNativeToManaged(IntPtr pNativeData) {
|
||||||
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
var ret = Eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
|
||||||
|
|
|
@ -13,6 +13,7 @@ mono_sublibs = [
|
||||||
]
|
]
|
||||||
|
|
||||||
blacklisted_files = [
|
blacklisted_files = [
|
||||||
|
'efl_class.eo',
|
||||||
'efl_canvas_text.eo',
|
'efl_canvas_text.eo',
|
||||||
'efl_canvas_scene3d.eo',
|
'efl_canvas_scene3d.eo',
|
||||||
'evas_canvas3d_camera.eo',
|
'evas_canvas3d_camera.eo',
|
||||||
|
|
|
@ -400,4 +400,17 @@ class TestInterfaceConcrete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestProvider
|
||||||
|
{
|
||||||
|
public static void test_find_provider()
|
||||||
|
{
|
||||||
|
// Tests only the direction C# -> C
|
||||||
|
var tmp = new Dummy.Numberwrapper();
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
Dummy.Numberwrapper provider = Dummy.Numberwrapper.static_cast(obj.FindProvider(typeof(Dummy.Numberwrapper)));
|
||||||
|
Test.AssertEquals(provider.GetType(), typeof(Dummy.Numberwrapper));
|
||||||
|
Test.AssertEquals(provider.GetNumber(), 1999);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1392,6 +1392,7 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
|
||||||
class.destructor;
|
class.destructor;
|
||||||
Efl.Object.constructor;
|
Efl.Object.constructor;
|
||||||
Efl.Part.part_get;
|
Efl.Part.part_get;
|
||||||
|
Efl.Object.provider_find;
|
||||||
Dummy.Test_Iface.emit_test_conflicted;
|
Dummy.Test_Iface.emit_test_conflicted;
|
||||||
Dummy.Test_Iface.emit_nonconflicted;
|
Dummy.Test_Iface.emit_nonconflicted;
|
||||||
Dummy.Test_Iface.iface_prop { get; set; }
|
Dummy.Test_Iface.iface_prop { get; set; }
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef struct Dummy_Test_Object_Data
|
||||||
Eina_List *list_for_accessor;
|
Eina_List *list_for_accessor;
|
||||||
int setter_only;
|
int setter_only;
|
||||||
int iface_prop;
|
int iface_prop;
|
||||||
|
Eo *provider;
|
||||||
} Dummy_Test_Object_Data;
|
} Dummy_Test_Object_Data;
|
||||||
|
|
||||||
typedef struct Dummy_Numberwrapper_Data
|
typedef struct Dummy_Numberwrapper_Data
|
||||||
|
@ -150,6 +151,9 @@ _dummy_test_object_efl_object_constructor(Eo *obj, Dummy_Test_Object_Data *pd)
|
||||||
pd->part_two = efl_add(DUMMY_TEST_OBJECT_CLASS, obj, efl_name_set(efl_added, "part_two"));
|
pd->part_two = efl_add(DUMMY_TEST_OBJECT_CLASS, obj, efl_name_set(efl_added, "part_two"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pd->provider = efl_add(DUMMY_NUMBERWRAPPER_CLASS, obj);
|
||||||
|
dummy_numberwrapper_number_set(pd->provider, 1999);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3920,6 +3924,14 @@ int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj
|
||||||
return pd->iface_prop;
|
return pd->iface_prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Eo * _dummy_test_object_efl_object_provider_find(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd, const Efl_Class *klass)
|
||||||
|
{
|
||||||
|
EINA_LOG_ERR("klass: %p, NUMBERWRAPPER: %p", klass, DUMMY_NUMBERWRAPPER_CLASS);
|
||||||
|
if (klass == DUMMY_NUMBERWRAPPER_CLASS)
|
||||||
|
return pd->provider;
|
||||||
|
return efl_provider_find(efl_super(obj, DUMMY_TEST_OBJECT_CLASS), klass);
|
||||||
|
}
|
||||||
|
|
||||||
/// Dummy.Child
|
/// Dummy.Child
|
||||||
|
|
||||||
static Efl_Object *
|
static Efl_Object *
|
||||||
|
|
Loading…
Reference in New Issue