forked from enlightenment/efl
eolian-mono: Add interface registration to inherited classes
Summary: Depends on D7635, D7634 Reviewers: woohyun, bu5hm4n, segfaultxavi, lauromoura Reviewed By: woohyun Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7636
This commit is contained in:
parent
7b342e8fdd
commit
adc2e674af
|
@ -71,7 +71,11 @@ struct native_function_definition_generator
|
||||||
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
|
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string klass_inherit_name = name_helpers::klass_inherit_name(*klass);
|
std::string klass_cast_name;
|
||||||
|
if (klass->type != attributes::class_type::interface_)
|
||||||
|
klass_cast_name = name_helpers::klass_inherit_name(*klass);
|
||||||
|
else
|
||||||
|
klass_cast_name = name_helpers::klass_interface_name(*klass);
|
||||||
|
|
||||||
if(!as_generator
|
if(!as_generator
|
||||||
(scope_tab
|
(scope_tab
|
||||||
|
@ -89,7 +93,7 @@ struct native_function_definition_generator
|
||||||
<< scope_tab << scope_tab << "if(wrapper != null) {\n"
|
<< scope_tab << scope_tab << "if(wrapper != null) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble()
|
<< scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble()
|
||||||
<< scope_tab << scope_tab << scope_tab << "try {\n"
|
<< scope_tab << scope_tab << scope_tab << "try {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << klass_inherit_name << ")wrapper)." << string
|
<< scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << klass_cast_name << ")wrapper)." << string
|
||||||
<< "(" << (native_argument_invocation % ", ") << ");\n"
|
<< "(" << (native_argument_invocation % ", ") << ");\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n"
|
<< scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
|
||||||
|
@ -98,7 +102,7 @@ struct native_function_definition_generator
|
||||||
<< eolian_mono::native_function_definition_epilogue(*klass)
|
<< eolian_mono::native_function_definition_epilogue(*klass)
|
||||||
<< scope_tab << scope_tab << "} else {\n"
|
<< scope_tab << scope_tab << "} else {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string
|
<< scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string
|
||||||
<< "(Efl.Eo.Globals.efl_super(obj, " << "EoKlass)" << *(", " << argument) << ");\n"
|
<< "(Efl.Eo.Globals.efl_super(obj, " << "GetEflClass())" << *(", " << argument) << ");\n"
|
||||||
<< scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << "}\n"
|
<< scope_tab << "}\n"
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
|
|
||||||
namespace eolian_mono {
|
namespace eolian_mono {
|
||||||
|
|
||||||
template <typename I>
|
// template <typename I>
|
||||||
struct function_registration_generator
|
struct function_registration_generator
|
||||||
{
|
{
|
||||||
I index_generator;
|
// I index_generator;
|
||||||
attributes::klass_def const* klass;
|
attributes::klass_def const* klass;
|
||||||
|
|
||||||
template <typename OutputIterator, typename Context>
|
template <typename OutputIterator, typename Context>
|
||||||
|
@ -34,7 +34,7 @@ struct function_registration_generator
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto index = index_generator();
|
// auto index = index_generator();
|
||||||
|
|
||||||
if(!as_generator(
|
if(!as_generator(
|
||||||
scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" <<
|
scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" <<
|
||||||
|
@ -43,12 +43,13 @@ struct function_registration_generator
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator
|
if(!as_generator
|
||||||
|
(scope_tab << scope_tab << "descs.Add(new Efl_Op_Description() {"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(scope_tab << scope_tab << "descs[" << index << "].api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\");\n"
|
<< "api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\")"
|
||||||
#else
|
#else
|
||||||
(scope_tab << scope_tab << "descs[" << index << "].api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\");\n"
|
<< "api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\")"
|
||||||
#endif
|
#endif
|
||||||
<< scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate);\n"
|
", func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate)});\n"
|
||||||
)
|
)
|
||||||
.generate(sink, std::make_tuple(f.c_name, f.c_name), context))
|
.generate(sink, std::make_tuple(f.c_name, f.c_name), context))
|
||||||
return false;
|
return false;
|
||||||
|
@ -59,10 +60,9 @@ struct function_registration_generator
|
||||||
|
|
||||||
struct function_registration_parameterized
|
struct function_registration_parameterized
|
||||||
{
|
{
|
||||||
template <typename I>
|
function_registration_generator operator()(attributes::klass_def const& klass) const
|
||||||
function_registration_generator<I> operator()(I i, attributes::klass_def const& klass) const
|
|
||||||
{
|
{
|
||||||
return {i, &klass};
|
return {&klass};
|
||||||
}
|
}
|
||||||
} const function_registration;
|
} const function_registration;
|
||||||
|
|
||||||
|
@ -70,15 +70,15 @@ struct function_registration_parameterized
|
||||||
|
|
||||||
namespace efl { namespace eolian { namespace grammar {
|
namespace efl { namespace eolian { namespace grammar {
|
||||||
|
|
||||||
template <typename I>
|
template <>
|
||||||
struct is_eager_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
|
struct is_eager_generator< ::eolian_mono::function_registration_generator> : std::true_type {};
|
||||||
template <typename I>
|
template <>
|
||||||
struct is_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {};
|
struct is_generator< ::eolian_mono::function_registration_generator> : std::true_type {};
|
||||||
|
|
||||||
namespace type_traits {
|
namespace type_traits {
|
||||||
|
|
||||||
template <typename I>
|
template <>
|
||||||
struct attributes_needed< ::eolian_mono::function_registration_generator<I>> : std::integral_constant<int, 1> {};
|
struct attributes_needed< ::eolian_mono::function_registration_generator> : std::integral_constant<int, 1> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} } }
|
} } }
|
||||||
|
|
|
@ -123,58 +123,57 @@ struct klass
|
||||||
// Interface class
|
// Interface class
|
||||||
if(class_type == "interface")
|
if(class_type == "interface")
|
||||||
{
|
{
|
||||||
auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
|
auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
|
||||||
|
|
||||||
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
|
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Mark the interface with the proper native Efl_Class* getter
|
// Mark the interface with the proper native Efl_Class* getter
|
||||||
if(!as_generator(lit("[") << name_helpers::interface_native_getter_attr_name(cls) << "]\n")
|
if(!as_generator(lit("[") << name_helpers::klass_native_inherit_name(cls) << "]\n")
|
||||||
.generate(sink, attributes::unused, iface_cxt))
|
.generate(sink, attributes::unused, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator
|
if(!as_generator
|
||||||
(
|
(
|
||||||
"public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : "
|
"public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : "
|
||||||
)
|
)
|
||||||
.generate(sink, name_helpers::klass_interface_name(cls), iface_cxt))
|
.generate(sink, name_helpers::klass_interface_name(cls), iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
for(auto first = std::begin(cls.immediate_inherits)
|
for(auto first = std::begin(cls.immediate_inherits)
|
||||||
, last = std::end(cls.immediate_inherits); first != last; ++first)
|
, last = std::end(cls.immediate_inherits); first != last; ++first)
|
||||||
{
|
{
|
||||||
if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_)
|
if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_)
|
||||||
if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt))
|
if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt))
|
if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt))
|
if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator(*(scope_tab << function_declaration)).generate(sink, cls.functions, iface_cxt))
|
if(!as_generator(*(scope_tab << function_declaration)).generate(sink, cls.functions, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator(*(scope_tab << async_function_declaration)).generate(sink, cls.functions, iface_cxt))
|
if(!as_generator(*(scope_tab << async_function_declaration)).generate(sink, cls.functions, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator(*(event_declaration)).generate(sink, cls.events, iface_cxt))
|
if(!as_generator(*(event_declaration)).generate(sink, cls.events, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto &&p : cls.parts)
|
for (auto &&p : cls.parts)
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
documentation(1)
|
documentation(1)
|
||||||
<< name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n"
|
<< name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n"
|
||||||
).generate(sink, p, iface_cxt))
|
).generate(sink, p, iface_cxt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, iface_cxt))
|
// End of interface declaration
|
||||||
return false;
|
if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
|
||||||
|
|
||||||
// End of interface declaration
|
|
||||||
if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events.
|
// Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events.
|
||||||
|
@ -276,17 +275,6 @@ struct klass
|
||||||
|
|
||||||
|
|
||||||
if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
|
if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
|
||||||
|
|
||||||
// Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces)
|
|
||||||
if(!as_generator(lit("public class ") << name_helpers::interface_native_getter_attr_name(cls) << " : Efl.Eo.NativeGetterAttr\n"
|
|
||||||
<< "{\n"
|
|
||||||
<< scope_tab << "public override IntPtr GetEflClass()\n"
|
|
||||||
<< scope_tab << "{\n"
|
|
||||||
<< scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
|
|
||||||
<< scope_tab << "}\n"
|
|
||||||
<< "}\n")
|
|
||||||
.generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inheritable class
|
// Inheritable class
|
||||||
|
@ -298,6 +286,7 @@ struct klass
|
||||||
if(!as_generator
|
if(!as_generator
|
||||||
(
|
(
|
||||||
documentation
|
documentation
|
||||||
|
<< "[" << name_helpers::klass_native_inherit_name(cls) << "]\n"
|
||||||
<< "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : "
|
<< "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : "
|
||||||
<< (klass_full_concrete_or_interface_name % ",") // classes
|
<< (klass_full_concrete_or_interface_name % ",") // classes
|
||||||
<< (inherit_classes.empty() ? "" : ",")
|
<< (inherit_classes.empty() ? "" : ",")
|
||||||
|
@ -359,16 +348,8 @@ struct klass
|
||||||
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
|
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t function_count = get_implementable_function_count(cls);
|
|
||||||
|
|
||||||
int function_registration_index = 0;
|
|
||||||
auto index_generator = [&function_registration_index]
|
|
||||||
{
|
|
||||||
return function_registration_index++;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Native Inherit class
|
// Native Inherit class
|
||||||
if(class_type == "class")
|
//if(class_type == "class")
|
||||||
{
|
{
|
||||||
auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
|
auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
|
||||||
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
|
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
|
||||||
|
@ -382,21 +363,21 @@ struct klass
|
||||||
|
|
||||||
if(!as_generator
|
if(!as_generator
|
||||||
(
|
(
|
||||||
"public " << class_type << " " << native_inherit_name << " " << (root ? "" : (": " + base_name)) <<"{\n"
|
"public class " << native_inherit_name << " " << (root ? ": Efl.Eo.NativeClass" : (": " + base_name)) <<"{\n"
|
||||||
<< scope_tab << (root ? "protected IntPtr EoKlass { get; set; }\n" : "\n")
|
// << scope_tab << (root ? "protected IntPtr EoKlass { get; set; }\n" : "\n")
|
||||||
<< scope_tab << "public " << (root ? "" : "new ") << "Efl_Op_Description[] GetEoOps()\n"
|
<< scope_tab << "public " << /*(root ? "" : "new ")*/ "override " << "System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "Efl_Op_Description[] descs = new Efl_Op_Description[" << grammar::int_ << "];\n"
|
<< scope_tab << scope_tab << "var descs = new System.Collections.Generic.List<Efl_Op_Description>();\n"
|
||||||
)
|
)
|
||||||
.generate(sink, function_count, inative_cxt))
|
.generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Native wrapper registration
|
// Native wrapper registration
|
||||||
if(!as_generator(*(function_registration(index_generator, cls)))
|
if(!as_generator(*(function_registration(cls)))
|
||||||
.generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
|
.generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
|
||||||
|
|
||||||
if(!root)
|
if(!root)
|
||||||
if(!as_generator(scope_tab << scope_tab << "descs = descs.Concat(base.GetEoOps()).ToArray();\n").generate(sink, attributes::unused, inative_cxt))
|
if(!as_generator(scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type));\n").generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator(
|
if(!as_generator(
|
||||||
|
@ -405,32 +386,23 @@ struct klass
|
||||||
).generate(sink, attributes::unused, inative_cxt))
|
).generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!as_generator
|
// Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces)
|
||||||
(scope_tab << "public " << (root ? "" : "new " ) << "byte class_initializer(IntPtr klass)\n"
|
if(!as_generator(
|
||||||
<< scope_tab << "{\n"
|
scope_tab << "public override IntPtr GetEflClass()\n"
|
||||||
<< scope_tab << scope_tab << "var descs = GetEoOps();\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "var count = descs.Length;\n"
|
<< scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
|
||||||
<< scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*count);\n"
|
<< scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << "IntPtr ptr = descs_ptr;\n"
|
).generate(sink, attributes::unused, inative_cxt))
|
||||||
<< scope_tab << scope_tab << "for(int i = 0; i != count; ++i)\n"
|
return false;
|
||||||
<< scope_tab << scope_tab << "{\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << "Marshal.StructureToPtr(descs[i], ptr, false);\n"
|
|
||||||
<< scope_tab << scope_tab << scope_tab << "ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0]));\n"
|
|
||||||
<< scope_tab << scope_tab << "}\n"
|
|
||||||
<< scope_tab << scope_tab << "Efl_Object_Ops ops;\n"
|
|
||||||
<< scope_tab << scope_tab << "ops.descs = descs_ptr;\n"
|
|
||||||
<< scope_tab << scope_tab << "ops.count = (UIntPtr)count;\n"
|
|
||||||
<< scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n"
|
|
||||||
<< scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n"
|
|
||||||
<< scope_tab << scope_tab << "Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n"
|
|
||||||
<< scope_tab << scope_tab << "EoKlass = klass;\n"
|
|
||||||
).generate(sink, attributes::unused, inative_cxt)) return false;
|
|
||||||
|
|
||||||
|
if(!as_generator(
|
||||||
|
scope_tab << "public 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, inative_cxt))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(!as_generator(scope_tab << scope_tab << "return 1;\n"
|
|
||||||
<< scope_tab << "}\n")
|
|
||||||
.generate(sink, attributes::unused, inative_cxt)) return false;
|
|
||||||
//
|
|
||||||
// Native method definitions
|
// Native method definitions
|
||||||
if(!as_generator(*(native_function_definition(cls)))
|
if(!as_generator(*(native_function_definition(cls)))
|
||||||
.generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
|
.generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false;
|
||||||
|
@ -451,8 +423,9 @@ struct klass
|
||||||
bool root = !helpers::has_regular_ancestor(cls);
|
bool root = !helpers::has_regular_ancestor(cls);
|
||||||
bool is_inherit = is_inherit_context(context);
|
bool is_inherit = is_inherit_context(context);
|
||||||
|
|
||||||
std::string class_getter = "return Efl.Eo.Globals.efl_class_get(handle);";
|
std::string class_getter = name_helpers::klass_get_name(cls) + "()";
|
||||||
std::string native_inherit_full_name = name_helpers::klass_full_native_inherit_name(cls);
|
std::string native_inherit_full_name = name_helpers::klass_full_native_inherit_name(cls);
|
||||||
|
auto inherit_name = name_helpers::klass_concrete_name(cls);
|
||||||
|
|
||||||
// The klass field is static but there is no problem if multiple C# classes inherit from this generated one
|
// The klass field is static but there is no problem if multiple C# classes inherit from this generated one
|
||||||
// as it is just a simple wrapper, forwarding the Eo calls either to the user API (where C#'s virtual method
|
// as it is just a simple wrapper, forwarding the Eo calls either to the user API (where C#'s virtual method
|
||||||
|
@ -464,7 +437,6 @@ struct klass
|
||||||
<< scope_tab << "public " << (root ? "" : "new ") << "static " << native_inherit_full_name << " nativeInherit = new " << native_inherit_full_name << "();\n"
|
<< scope_tab << "public " << (root ? "" : "new ") << "static " << native_inherit_full_name << " nativeInherit = new " << native_inherit_full_name << "();\n"
|
||||||
).generate(sink, attributes::unused, context))
|
).generate(sink, attributes::unused, context))
|
||||||
return false;
|
return false;
|
||||||
class_getter = "return klass;";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string raw_klass_modifier;
|
std::string raw_klass_modifier;
|
||||||
|
@ -477,7 +449,10 @@ struct klass
|
||||||
scope_tab << "///<summary>Pointer to the native class description.</summary>\n"
|
scope_tab << "///<summary>Pointer to the native class description.</summary>\n"
|
||||||
<< scope_tab << "public " << raw_klass_modifier << "System.IntPtr NativeClass {\n"
|
<< scope_tab << "public " << raw_klass_modifier << "System.IntPtr NativeClass {\n"
|
||||||
<< scope_tab << scope_tab << "get {\n"
|
<< scope_tab << scope_tab << "get {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << class_getter << "\n" //return klass; }\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 << "else\n"
|
||||||
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "return Efl.Eo.Globals.klasses[((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))
|
||||||
|
@ -534,7 +509,8 @@ struct klass
|
||||||
scope_tab << "///<summary>Creates a new instance.</summary>\n"
|
scope_tab << "///<summary>Creates a new instance.</summary>\n"
|
||||||
<< scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
|
<< scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
|
||||||
<< scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
|
<< scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
|
||||||
<< scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : base(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
|
<< scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : "
|
||||||
|
"base(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
|
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
|
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
|
||||||
|
@ -543,7 +519,7 @@ struct klass
|
||||||
<< scope_tab << "}\n"
|
<< scope_tab << "}\n"
|
||||||
|
|
||||||
<< scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n"
|
<< scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n"
|
||||||
<< scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent, ref IntPtr target_klass) : base(class_initializer, klass_name, base_klass, managed_type, parent, ref target_klass) {}\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 << "///<summary>Constructs an instance from a native pointer.</summary>\n"
|
<< scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
|
||||||
<< scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
|
<< scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
|
||||||
|
@ -559,7 +535,7 @@ struct klass
|
||||||
scope_tab << "///<summary>Creates a new instance.</summary>\n"
|
scope_tab << "///<summary>Creates a new instance.</summary>\n"
|
||||||
<< scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
|
<< scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
|
||||||
<< scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
|
<< scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
|
||||||
<< scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
|
<< scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
|
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
|
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
|
||||||
|
@ -567,22 +543,22 @@ struct klass
|
||||||
<< scope_tab << scope_tab << "FinishInstantiation();\n"
|
<< scope_tab << scope_tab << "FinishInstantiation();\n"
|
||||||
<< scope_tab << "}\n"
|
<< scope_tab << "}\n"
|
||||||
|
|
||||||
<< scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent, ref IntPtr target_klass)\n"
|
<< scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
|
||||||
<< scope_tab << "{\n"
|
<< scope_tab << "{\n"
|
||||||
<< scope_tab << scope_tab << "inherited = 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 (target_klass == System.IntPtr.Zero) {\n"
|
<< scope_tab << scope_tab << scope_tab << "if (!Efl.Eo.Globals.klasses.ContainsKey(((object)this).GetType())) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
|
<< scope_tab << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\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 << "target_klass = Efl.Eo.Globals.register_class(class_initializer, klass_name, base_klass, 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 << "if (target_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 << 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 << "}\n"
|
||||||
<< 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 << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "}\n"
|
<< scope_tab << scope_tab << scope_tab << "}\n"
|
||||||
<< scope_tab << scope_tab << scope_tab << "actual_klass = target_klass;\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"
|
||||||
|
|
|
@ -379,18 +379,6 @@ inline std::string klass_get_full_name(T const& clsname)
|
||||||
return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname);
|
return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline std::string interface_native_getter_attr_name(T const& clsname)
|
|
||||||
{
|
|
||||||
return klass_interface_name(clsname) + "NativeGetterAttr";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline std::string interface_native_getter_attr_full_name(T const& clsname)
|
|
||||||
{
|
|
||||||
return klass_full_interface_name(clsname) + "NativeGetterAttr";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
inline std::string managed_event_name(std::string const& name)
|
inline std::string managed_event_name(std::string const& name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,11 +150,14 @@ 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);
|
||||||
|
|
||||||
public static IntPtr register_class(class_initializer initializer, String class_name, IntPtr base_klass, System.Type type)
|
public static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type)
|
||||||
{
|
{
|
||||||
ClassDescription description;
|
ClassDescription description;
|
||||||
description.version = 2; // EO_VERSION
|
description.version = 2; // EO_VERSION
|
||||||
|
@ -165,39 +168,113 @@ public class Globals {
|
||||||
description.class_constructor = IntPtr.Zero;
|
description.class_constructor = IntPtr.Zero;
|
||||||
description.class_destructor = IntPtr.Zero;
|
description.class_destructor = IntPtr.Zero;
|
||||||
|
|
||||||
if(initializer != null)
|
class_initializer init = (IntPtr kls) =>
|
||||||
description.class_initializer = Marshal.GetFunctionPointerForDelegate(initializer);
|
{
|
||||||
|
return Globals.class_initializer_call(kls, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
description.class_initializer = Marshal.GetFunctionPointerForDelegate(init);
|
||||||
|
|
||||||
IntPtr description_ptr = Eina.MemoryNative.Alloc(Marshal.SizeOf(description));
|
IntPtr description_ptr = Eina.MemoryNative.Alloc(Marshal.SizeOf(description));
|
||||||
Marshal.StructureToPtr(description, description_ptr, false);
|
Marshal.StructureToPtr(description, description_ptr, false);
|
||||||
|
|
||||||
var interface_list = EoG.get_efl_interfaces(type);
|
var interface_list = EoG.get_efl_interfaces(type);
|
||||||
|
|
||||||
|
System.Console.WriteLine ("Interafaces: {0}", interface_list.Count);
|
||||||
|
|
||||||
Eina.Log.Debug("Going to register!");
|
Eina.Log.Debug("Going to register!");
|
||||||
IntPtr klass = EoG.call_efl_class_new(description_ptr, base_klass, interface_list);
|
IntPtr klass = EoG.call_efl_class_new(description_ptr, base_klass, interface_list);
|
||||||
if(klass == IntPtr.Zero)
|
if(klass == IntPtr.Zero)
|
||||||
|
{
|
||||||
Eina.Log.Error("klass was not registered");
|
Eina.Log.Error("klass was not registered");
|
||||||
|
Console.WriteLine("klass was not registered");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Eina.Log.Debug("Registered class successfully");
|
Eina.Log.Debug("Registered class successfully");
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
public static List<IntPtr> get_efl_interfaces(System.Type type)
|
public static List<IntPtr> get_efl_interfaces(System.Type type)
|
||||||
{
|
{
|
||||||
|
System.Type base_type = type.BaseType;
|
||||||
|
|
||||||
var ifaces_lst = new List<IntPtr>();
|
var ifaces_lst = new List<IntPtr>();
|
||||||
|
var base_ifaces = base_type.GetInterfaces();
|
||||||
var ifaces = type.GetInterfaces();
|
var ifaces = type.GetInterfaces();
|
||||||
foreach (var iface in ifaces)
|
foreach (var iface in ifaces)
|
||||||
{
|
{
|
||||||
var attrs = System.Attribute.GetCustomAttributes(iface);
|
if (!System.Array.Exists(base_ifaces, element => element == iface))
|
||||||
foreach (var attr in attrs)
|
|
||||||
{
|
{
|
||||||
if (attr is Efl.Eo.NativeGetterAttr) {
|
var attrs = System.Attribute.GetCustomAttributes(iface);
|
||||||
ifaces_lst.Add(((Efl.Eo.NativeGetterAttr)attr).GetEflClass());
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
if (attr is Efl.Eo.NativeClass) {
|
||||||
|
ifaces_lst.Add(((Efl.Eo.NativeClass)attr).GetEflClass());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ifaces_lst;
|
return ifaces_lst;
|
||||||
}
|
}
|
||||||
|
private static Efl.Eo.NativeClass get_native_class(System.Type type)
|
||||||
|
{
|
||||||
|
var attrs = System.Attribute.GetCustomAttributes(type);
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
if (attr is Efl.Eo.NativeClass) {
|
||||||
|
return (Efl.Eo.NativeClass)attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public static byte class_initializer_call(IntPtr klass, System.Type type)
|
||||||
|
{
|
||||||
|
Console.WriteLine("class_intiailizer_call 0x{1} {0}", type, klass);
|
||||||
|
Efl.Eo.NativeClass nativeClass = get_native_class(type.BaseType);
|
||||||
|
|
||||||
|
if (nativeClass != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("nativeClass != null");
|
||||||
|
var descs = nativeClass.GetEoOps(type);
|
||||||
|
var count = descs.Count;
|
||||||
|
|
||||||
|
var all_interfaces = type.GetInterfaces();
|
||||||
|
var base_interfaces = type.BaseType.GetInterfaces();
|
||||||
|
foreach (var iface in all_interfaces)
|
||||||
|
{
|
||||||
|
if (!System.Array.Exists(base_interfaces, element => element == iface))
|
||||||
|
{
|
||||||
|
var nc = get_native_class(iface);
|
||||||
|
if(nc != null)
|
||||||
|
{
|
||||||
|
var moredescs = nc.GetEoOps(type);
|
||||||
|
Console.WriteLine("adding {0} more descs to registration", moredescs.Count);
|
||||||
|
descs.AddRange(moredescs);
|
||||||
|
count = descs.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*count);
|
||||||
|
IntPtr ptr = descs_ptr;
|
||||||
|
for(int i = 0; i != count; ++i)
|
||||||
|
{
|
||||||
|
Marshal.StructureToPtr(descs[i], ptr, false);
|
||||||
|
ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0]));
|
||||||
|
}
|
||||||
|
Efl_Object_Ops ops;
|
||||||
|
ops.descs = descs_ptr;
|
||||||
|
ops.count = (UIntPtr)count;
|
||||||
|
IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));
|
||||||
|
Marshal.StructureToPtr(ops, ops_ptr, false);
|
||||||
|
Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);
|
||||||
|
//EoKlass = klass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.WriteLine("nativeClass == null");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
public static IntPtr call_efl_class_new(IntPtr desc, IntPtr bk, List<IntPtr> il = null)
|
public static IntPtr call_efl_class_new(IntPtr desc, IntPtr bk, List<IntPtr> il = null)
|
||||||
{
|
{
|
||||||
IntPtr nul = IntPtr.Zero;
|
IntPtr nul = IntPtr.Zero;
|
||||||
|
@ -259,11 +336,17 @@ public class Globals {
|
||||||
public static IntPtr instantiate_start(IntPtr klass, Efl.Object parent)
|
public static IntPtr instantiate_start(IntPtr klass, Efl.Object parent)
|
||||||
{
|
{
|
||||||
Eina.Log.Debug($"Instantiating from klass 0x{klass.ToInt64():x}");
|
Eina.Log.Debug($"Instantiating from klass 0x{klass.ToInt64():x}");
|
||||||
|
Console.WriteLine($"Instantiating from klass 0x{klass.ToInt64():x}");
|
||||||
System.IntPtr parent_ptr = System.IntPtr.Zero;
|
System.IntPtr parent_ptr = System.IntPtr.Zero;
|
||||||
if(parent != null)
|
if(parent != null)
|
||||||
parent_ptr = parent.NativeHandle;
|
parent_ptr = parent.NativeHandle;
|
||||||
|
|
||||||
System.IntPtr eo = Efl.Eo.Globals._efl_add_internal_start("file", 0, klass, parent_ptr, 1, 0);
|
System.IntPtr eo = Efl.Eo.Globals._efl_add_internal_start("file", 0, klass, parent_ptr, 1, 0);
|
||||||
|
if (eo == System.IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new Exception("Instantiation failed");
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Eo instance right after internal_start 0x{eo.ToInt64():x} with refcount {Efl.Eo.Globals.efl_ref_count(eo)}");
|
Console.WriteLine($"Eo instance right after internal_start 0x{eo.ToInt64():x} with refcount {Efl.Eo.Globals.efl_ref_count(eo)}");
|
||||||
Console.WriteLine($"Parent was 0x{parent_ptr.ToInt64()}");
|
Console.WriteLine($"Parent was 0x{parent_ptr.ToInt64()}");
|
||||||
return eo;
|
return eo;
|
||||||
|
@ -415,9 +498,10 @@ public static class Config
|
||||||
AllowMultiple = false,
|
AllowMultiple = false,
|
||||||
Inherited = true)
|
Inherited = true)
|
||||||
]
|
]
|
||||||
public abstract class NativeGetterAttr : System.Attribute
|
public abstract class NativeClass : System.Attribute
|
||||||
{
|
{
|
||||||
public abstract IntPtr GetEflClass();
|
public abstract IntPtr GetEflClass();
|
||||||
|
public abstract System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IWrapper
|
public interface IWrapper
|
||||||
|
|
|
@ -24,11 +24,13 @@ class TestInheritance
|
||||||
{
|
{
|
||||||
override public void IntOut (int x, out int y)
|
override public void IntOut (int x, out int y)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("IntOut");
|
||||||
y = 10*x;
|
y = 10*x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string StringshareTest (string i)
|
public string StringshareTest (string i)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("StringshareTest");
|
||||||
return "Hello World";
|
return "Hello World";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +46,8 @@ class TestInheritance
|
||||||
{
|
{
|
||||||
var obj = new Inherit2();
|
var obj = new Inherit2();
|
||||||
int i = Dummy.InheritHelper.ReceiveDummyAndCallIntOut(obj);
|
int i = Dummy.InheritHelper.ReceiveDummyAndCallIntOut(obj);
|
||||||
string s = Dummy.InheritHelper.ReceiveDummyAndCallInStringshare(obj);
|
|
||||||
Test.AssertEquals (50, i);
|
Test.AssertEquals (50, i);
|
||||||
|
string s = Dummy.InheritHelper.ReceiveDummyAndCallInStringshare(obj);
|
||||||
Test.AssertEquals ("Hello World", s);
|
Test.AssertEquals ("Hello World", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue