eolian-mono: Provide constructor parameters based on the constructors

section of the Eo files.

Reviewers: woohyun, segfaultxavi, bu5hm4n, felipealmeida

Reviewed By: segfaultxavi

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7789
This commit is contained in:
Felipe Magno de Almeida 2019-02-01 14:03:02 -05:00 committed by Christopher Michael
parent e414450404
commit 0223bb29df
12 changed files with 399 additions and 85 deletions

View File

@ -84,6 +84,29 @@ struct documentation_generator
return name;
}
static std::string function_conversion(attributes::function_def const& func)
{
attributes::klass_def klass(get_klass(func.klass, func.unit), func.unit);
std::string name = name_helpers::klass_full_concrete_or_interface_name(klass);
switch (func.type)
{
// managed_method_name takes care of reordering the function name so the get/set goes first
// for properties
case attributes::function_type::method:
case attributes::function_type::prop_set:
case attributes::function_type::prop_get:
if (blacklist::is_function_blacklisted(func.c_name))return "";
name += ".";
name += name_helpers::managed_method_name(klass.eolian_name, func.name);
break;
default:
// No need to deal with property as function_defs are converted to get/set when building a given klass_def.
break;
}
return name;
}
// Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail)
{
@ -299,6 +322,31 @@ struct documentation_generator
{
return generate_tag_summary(sink, doc.full_text, context);
}
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const
{
// Not sure if this is the best way to generate a reference outside the full doc generator.
auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
auto func = ctor.function;
auto eolian_klass = get_klass(func.klass, unit);
attributes::klass_def klass(eolian_klass, unit);
std::string summary;
if (func.type == attributes::function_type::prop_set)
summary = func.property_documentation.summary;
else
summary = func.documentation.summary;
for (auto &&param : ctor.function.parameters)
{
if (!as_generator(
scope_tab << "///<param name=\"" << constructor_parameter_name(ctor) << "\">" << summary << " See <see cref=\"" << function_conversion(func) << "\"/></param>\n"
).generate(sink, param, context))
return false;
}
return true;
}
};
struct documentation_terminal

View File

@ -221,6 +221,12 @@ inline bool is_unique_event(attributes::event_def const& evt
});
}
inline std::vector<attributes::constructor_def> reorder_constructors(std::vector<attributes::constructor_def> constructors)
{
auto is_required = [](attributes::constructor_def const& ctr) { return !ctr.is_optional; };
std::stable_partition(constructors.begin(), constructors.end(), is_required);
return constructors;
}
} // namespace helpers

View File

@ -220,15 +220,16 @@ struct klass
if (!generate_fields(sink, cls, concrete_cxt))
return false;
bool root = !helpers::has_regular_ancestor(cls);
if (!as_generator
(
scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
<< ")] internal static extern System.IntPtr\n"
<< scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
<< scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
<< scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n"
<< scope_tab << "///<summary>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 << "public " << concrete_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "handle = raw;\n"
<< scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
<< scope_tab << scope_tab << "register_event_proxies();\n"
<< scope_tab << "}\n"
)
@ -503,48 +504,44 @@ struct klass
).generate(sink, attributes::unused, context))
return false;
auto constructors = helpers::reorder_constructors(cls.get_all_constructors());
if (!root)
{
return as_generator(
// Public (API) constructors
if (!as_generator(
scope_tab << "///<summary>Creates a new instance.</summary>\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 << "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"
<< *(documentation)
// 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 << 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 << "{\n"
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
<< scope_tab << scope_tab << "}\n"
<< *(scope_tab << scope_tab << constructor_invocation << "\n" )
<< scope_tab << scope_tab << "FinishInstantiation();\n"
<< scope_tab << "}\n"
<< scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</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 << "///<summary>Constructs an instance from a native pointer.</summary>\n"
<< scope_tab << "///<summary>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 << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
<< scope_tab << scope_tab << "register_event_proxies();\n"
<< scope_tab << "}\n"
).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
return false;
// Internal constructors
if (!root)
{
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 << "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"
).generate(sink, attributes::unused, context);
}
}
// Detailed constructors go only in root classes.
return as_generator(
scope_tab << "///<summary>Creates a new instance.</summary>\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 << "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 << scope_tab << "if (init_cb != null) {\n"
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
<< scope_tab << scope_tab << "}\n"
<< scope_tab << scope_tab << "FinishInstantiation();\n"
<< scope_tab << "}\n"
<< scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
/// 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 << "{\n"
<< scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n"
<< scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
@ -574,12 +571,6 @@ struct klass
<< scope_tab << scope_tab << "Eina.Error.RaiseIfUnhandledException();\n"
<< scope_tab << "}\n"
<< scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
<< scope_tab << "public " << inherit_name << "(System.IntPtr raw)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "handle = raw;\n"
<< scope_tab << scope_tab << "register_event_proxies();\n"
<< scope_tab << "}\n"
).generate(sink, attributes::unused, context);
}

View File

@ -187,6 +187,12 @@ inline std::string managed_method_name(std::string const& klass, std::string con
return candidate;
}
inline std::string managed_name(std::string const& name, char separator='_')
{
auto tokens = utils::split(name, separator);
return utils::to_pascal_case(tokens);
}
inline std::string managed_method_name(attributes::function_def const& f)
{
return managed_method_name(f.klass.eolian_name, f.name);
@ -420,7 +426,12 @@ bool close_namespaces(OutputIterator sink, std::vector<std::string> const& names
return as_generator(close_namespace).generate(sink, namespaces, context);
}
std::string constructor_managed_name(std::string full_name)
{
auto tokens = utils::split(full_name, '.');
return managed_name(tokens.at(tokens.size()-1));
}
} // namespace name_helpers

View File

@ -3,6 +3,7 @@
#include "grammar/generator.hpp"
#include "grammar/klass_def.hpp"
#include "grammar/attribute_reorder.hpp"
#include "grammar/case.hpp"
#include "helpers.hh"
#include "marshall_type.hh"
@ -34,6 +35,10 @@ namespace eolian_mono {
struct native_convert_return_variable_generator;
struct convert_function_pointer_generator;
struct native_convert_function_pointer_generator;
struct constructor_param_generator;
struct constructor_invocation_generator;
struct constructor_parameter_name_generator;
struct constructor_parameter_name_paremeterized;
}
namespace efl { namespace eolian { namespace grammar {
@ -232,6 +237,38 @@ template <>
struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_param_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_invocation_generator> : std::integral_constant<int, 1> {};
}
template <>
struct is_eager_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
template <>
struct is_generator< ::eolian_mono::constructor_parameter_name_paremeterized> : std::true_type {};
namespace type_traits {
template <>
struct attributes_needed< ::eolian_mono::constructor_parameter_name_generator> : std::integral_constant<int, 1> {};
}
} } }
namespace eolian_mono {
@ -1436,6 +1473,89 @@ struct native_convert_function_pointer_generator
} const native_convert_function_pointer {};
struct constructor_parameter_name_generator
{
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
auto target_name = name_helpers::constructor_managed_name(ctor.name);
// Only multi-valued constructing methods get their actual parameter names
if (ctor.function.parameters.size() > 1)
target_name += '_' + param.param_name;
auto name = name_helpers::managed_name(target_name);
name[0] = std::tolower(name[0]);
return as_generator(string).generate(sink, name, context);
}
attributes::constructor_def const& ctor;
};
struct constructor_parameter_name_parameterized
{
constructor_parameter_name_generator const operator()(attributes::constructor_def const& ctor) const
{
return {ctor};
}
} const constructor_parameter_name;
// Generates the parameters for the given constructor
// If the constructor receives multiple parameters, they get the name
// of the constructor plus the name of the parameter (e.g. DefineParentData, DefineIndex)
struct constructor_param_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
{
auto params = ctor.function.parameters;
if (!as_generator(
efl::eolian::grammar::attribute_reorder<1, -1>
(type(false, ctor.is_optional) << " " << constructor_parameter_name(ctor) << (ctor.is_optional ? " = null" : "")) % ","
).generate(sink, params, context))
return false;
// }
return true;
}
} const constructor_param;
// Generates the invocation of the given parameter
struct constructor_invocation_generator
{
template<typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
{
auto params = ctor.function.parameters;
if (!as_generator(
"if (" <<
(efl::eolian::grammar::attribute_reorder<-1>
("Efl.Eo.Globals.ParamHelperCheck(" << constructor_parameter_name(ctor) << ")") % "||") << ")\n"
<< scope_tab << scope_tab << scope_tab << name_helpers::managed_method_name(ctor.function) << "("
).generate(sink, params, context))
return false;
size_t idx = 0;
for (auto&& param : params)
{
idx++;
if (!as_generator(
"Efl.Eo.Globals.GetParamHelper(" << constructor_parameter_name(ctor) << ")" << ((idx < params.size()) ? ", " : "")
).generate(sink, param, context))
return false;
}
if (!as_generator(");").generate(sink, attributes::unused, context))
return false;
return true;
}
} const constructor_invocation;
}
#endif

View File

@ -14,29 +14,29 @@ struct visitor_generate;
struct type_generator
{
type_generator(bool is_return = false)
: is_return(is_return) {}
type_generator(bool is_return = false, bool is_optional = false)
: is_return(is_return), is_optional(is_optional) {}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
{
return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr, is_optional});
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
{
return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
, param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
, param.direction != attributes::parameter_direction::in, false, param.type.is_ptr, is_optional});
}
bool is_return;
bool is_return, is_optional;
};
struct type_terminal
{
type_generator const operator()(bool is_return) const
type_generator const operator()(bool is_return, bool is_optional = false) const
{
return type_generator(is_return);
return type_generator(is_return, is_optional);
}
} const type = {};

View File

@ -34,6 +34,20 @@ attributes::regular_type_def replace_base_integer(attributes::regular_type_def v
}
}
template <typename T>
attributes::regular_type_def replace_base_opt_integer(attributes::regular_type_def v)
{
bool s = std::is_signed<T>::value;
switch (sizeof(T))
{
case 1: return s ? replace_base_type(v, " sbyte?") : replace_base_type(v, " byte?");
case 2: return s ? replace_base_type(v, " short?") : replace_base_type(v, " ushort?");
case 4: return s ? replace_base_type(v, " int?") : replace_base_type(v, " uint?");
case 8: return s ? replace_base_type(v, " long?") : replace_base_type(v, " ulong?");
default: return v;
}
}
inline
attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
{
@ -63,6 +77,7 @@ struct visitor_generate
bool is_out;
bool is_return;
bool is_ptr;
mutable bool is_optional;
typedef visitor_generate<OutputIterator, Context> visitor_type;
typedef bool result_type;
@ -76,6 +91,40 @@ struct visitor_generate
eina::optional<bool> has_own;
std::function<attributes::type_def::variant_type()> function;
}
const optional_match_table[] =
{
// signed primitives
{"byte", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
, {"float", nullptr, [&] { return replace_base_type(regular, " float?"); }}
, {"double", nullptr, [&] { return replace_base_type(regular, " double?"); }}
, {"bool", nullptr, [&] { return replace_base_type(regular, " bool?"); }}
, {"short", nullptr, [&] { return replace_base_opt_integer<short>(regular); }}
, {"int", nullptr, [&] { return replace_base_opt_integer<int>(regular); }}
, {"long", nullptr, [&] { return replace_base_opt_integer<long>(regular); }}
, {"llong", nullptr, [&] { return replace_base_opt_integer<long long>(regular); }}
, {"int8", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
, {"int16", nullptr, [&] { return replace_base_type(regular, " short?"); }}
, {"int32", nullptr, [&] { return replace_base_type(regular, " int?"); }}
, {"int64", nullptr, [&] { return replace_base_type(regular, " long?"); }}
, {"ssize", nullptr, [&] { return replace_base_opt_integer<ssize_t>(regular); }}
// unsigned primitives
, {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
, {"ushort", nullptr, [&] { return replace_base_opt_integer<unsigned short>(regular); }}
, {"uint", nullptr, [&] { return replace_base_opt_integer<unsigned int>(regular); }}
, {"ulong", nullptr, [&] { return replace_base_opt_integer<unsigned long>(regular); }}
, {"ullong", nullptr, [&] { return replace_base_opt_integer<unsigned long long>(regular); }}
, {"uint8", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
, {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort?"); }}
, {"uint32", nullptr, [&] { return replace_base_type(regular, " uint?"); }}
, {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong?"); }}
, {"size", nullptr, [&] { return replace_base_opt_integer<size_t>(regular); }}
, {"ptrdiff", nullptr, [&] { return replace_base_opt_integer<ptrdiff_t>(regular); }}
, {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
, {"uintptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
, {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
};
struct match
const match_table[] =
{
// signed primitives
@ -153,6 +202,29 @@ struct visitor_generate
};
std::string full_type_name = name_helpers::type_full_eolian_name(regular);
if(eina::optional<bool> b = call_match
(optional_match_table
, [&] (match const& m)
{
return is_optional
&& (!m.name || *m.name == regular.base_type || *m.name == full_type_name)
&& (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
;
}
, [&] (attributes::type_def::variant_type const& v)
{
return v.visit(*this); // we want to keep is_out info
}))
{
return *b;
}
else if (is_optional && (regular.is_struct() || regular.is_enum() || regular.is_struct_opaque()))
{
attributes::regular_type_def r = regular;
r.base_type.push_back('?');
is_optional = false;
return (*this)(r);
}
else if(eina::optional<bool> b = call_match
(match_table
, [&] (match const& m)
{

View File

@ -157,6 +157,23 @@ public class Globals {
public delegate byte class_initializer(IntPtr klass);
public static T GetParamHelper<T>(Nullable<T> v) where T : struct
{
return v.Value;
}
public static U GetParamHelper<U>(U v)
{
return v;
}
public static bool ParamHelperCheck<T>(Nullable<T> v) where T : struct
{
return v.HasValue;
}
public static bool ParamHelperCheck<U>(U v)
{
return v != null;
}
public static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type)
{
ClassDescription description;

View File

@ -114,43 +114,6 @@ class TestEoNames
}
}
class TestEoConstructingMethods
{
public static void constructing_method()
{
bool called = false;
string name = "Test object";
var obj = new Dummy.TestObject(null, (Dummy.TestObject a) => {
called = true;
Console.WriteLine("callback: obj NativeHandle: {0:x}", a.NativeHandle);
a.SetName(name);
});
Test.Assert(called);
Test.AssertEquals(name, obj.GetName());
}
private class Derived : Dummy.TestObject
{
public Derived(Dummy.TestObject parent = null,
Dummy.TestObject.ConstructingMethod cb = null) : base(parent, cb) {
}
}
public static void constructing_method_inherit()
{
bool called = false;
string name = "Another test object";
Derived obj = new Derived(null, (Dummy.TestObject a) => {
called = true;
a.SetComment(name);
});
Test.Assert(called);
Test.AssertEquals(name, obj.GetComment());
}
}
class TestEoParent
{
public static void basic_parent()
@ -365,6 +328,9 @@ class TestEoGrandChildrenFinalize
public sealed class GrandChild : Dummy.Child
{
public GrandChild() : base(null, "", 0.0) { }
public int receivedValue = 0;
public override Efl.Object FinalizeAdd()
{
@ -380,4 +346,27 @@ class TestEoGrandChildrenFinalize
}
}
class TestConstructors
{
public static void test_simple_constructor()
{
int iface_prop = 42;
string a = "LFE";
double b = 3.14;
var obj = new Dummy.Child(null, a, b, iface_prop);
Test.AssertEquals(iface_prop, obj.IfaceProp);
obj = new Dummy.Child(parent: null, ifaceProp : iface_prop, doubleParamsA : a, doubleParamsB : b);
Test.AssertEquals(iface_prop, obj.IfaceProp);
}
public static void test_optional_constructor()
{
string a = "LFE";
double b = 3.14;
var obj = new Dummy.Child(null, a, b);
Test.Assert(!obj.GetIfaceWasSet());
}
}
}

View File

@ -168,11 +168,10 @@ class TestEoEvents
{
int received = 0;
int sent = 42;
var obj = new Dummy.TestObject(null, (Dummy.TestObject t) => {
t.EvtWithIntEvt += (object sender, Dummy.TestObjectEvtWithIntEvt_Args e) => {
received = e.arg;
};
});
var obj = new Dummy.TestObject();
obj.EvtWithIntEvt += (object sender, Dummy.TestObjectEvtWithIntEvt_Args e) => {
received = e.arg;
};
obj.EmitEventWithInt(sent);

View File

@ -2,8 +2,29 @@ import eina_types;
class Dummy.Child extends Dummy.Test_Object {
methods {
double_params {
params {
@in a: string;
@in b: double;
}
}
@property iface_was_set {
get {}
values {
data: bool;
}
}
}
constructors {
Dummy.Test_Iface.iface_prop @optional;
.double_params;
}
implements {
Dummy.Test_Iface.iface_prop { get; set; }
class.constructor;
class.destructor;
Efl.Object.constructor;
}
}

View File

@ -82,6 +82,10 @@ typedef struct Dummy_Numberwrapper_Data
typedef struct Dummy_Child_Data
{
int iface_prop;
const char* a;
double b;
Eina_Bool iface_was_set;
} Dummy_Child_Data;
typedef struct Dummy_Inherit_Helper_Data
@ -3936,6 +3940,42 @@ int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj
}
/// Dummy.Child
static Efl_Object *
_dummy_child_efl_object_constructor(Eo *obj, Dummy_Child_Data *pd)
{
efl_constructor(efl_super(obj, DUMMY_CHILD_CLASS));
pd->iface_prop = 1984;
pd->iface_was_set = EINA_FALSE;
return obj;
}
void _dummy_child_dummy_test_iface_iface_prop_set(EINA_UNUSED Eo *obj, Dummy_Child_Data *pd, int value)
{
pd->iface_prop = value;
pd->iface_was_set = EINA_TRUE;
}
int _dummy_child_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj, Dummy_Child_Data *pd)
{
return pd->iface_prop;
}
void _dummy_child_double_params(EINA_UNUSED Eo* obj, Dummy_Child_Data *pd, const char* a, double b)
{
if (pd->a)
free((void*)pd->a);
pd->a = malloc(sizeof(char)*(strlen(a) + 1));
strcpy((char*)pd->a, a);
pd->b = b;
}
Eina_Bool _dummy_child_iface_was_set_get(EINA_UNUSED const Eo* obj, Dummy_Child_Data *pd)
{
return pd->iface_was_set;
}
EOLIAN static void
_dummy_child_class_constructor(Efl_Class *klass)
{