efl-mono: Fix marshalling of struct in event data.

Summary:
Previously, we just converted through PtrToStructure, which didn't have
the full marshalling info converting from the internal one to the
external.

This fixes the usage of the Efl.Loop.arguments event.

Also renamed the ToExternal methods to ToManaged, to make clearer that
the output struct is the one intended to be used from the managed code.

Also fixed a minor styling in the generated code (making it easier to be
inspected).

Depends on D7538

Reviewers: segfaultxavi, felipealmeida, bu5hm4n

Reviewed By: bu5hm4n

Subscribers: bu5hm4n, cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7539
This commit is contained in:
Lauro Moura 2018-12-21 00:15:17 -03:00 committed by Felipe Magno de Almeida
parent 49d4d44926
commit ede219c453
6 changed files with 62 additions and 20 deletions

View File

@ -25,10 +25,19 @@ struct unpack_event_args_visitor
std::string const& arg = "evt.Info";
std::string arg_type = name_helpers::type_full_managed_name(regular);
// Structs are usually passed by pointer to events, like having a ptr<> modifier
if (type.is_ptr || regular.is_struct())
return as_generator("(" + arg_type + ")Marshal.PtrToStructure(" + arg + ", typeof(" + arg_type + "))")
if (regular.is_struct())
{
// Structs are usually passed by pointer to events, like having a ptr<> modifier
// Uses implicit conversion from IntPtr
return as_generator(
" evt.Info;"
).generate(sink, attributes::unused, *context);
}
else if (type.is_ptr)
{
return as_generator("(" + arg_type + ")Marshal.PtrToStructure(" + arg + ", typeof(" + arg_type + "))")
.generate(sink, attributes::unused, *context);
}
using attributes::regular_type_def;
struct match
@ -84,21 +93,15 @@ struct event_argument_wrapper_generator
return true;
std::string evt_name = name_helpers::managed_event_name(evt.name);
std::string arg_type;
if (!as_generator(type).generate(std::back_inserter(arg_type), *etype, efl::eolian::grammar::context_null()))
{
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Failed to get argument type for event " << evt.name;
return false;
}
return as_generator("///<summary>Event argument wrapper for event <see cref=\""
<< join_namespaces(evt.klass.namespaces, '.', managed_namespace)
<< klass_interface_name(evt.klass) << "." << evt_name << "\"/>.</summary>\n"
<< "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n"
<< scope_tab << "///<summary>Actual event payload.</summary>\n"
<< scope_tab << "public " << arg_type << " arg { get; set; }\n"
<< scope_tab << "public " << type << " arg { get; set; }\n"
<< "}\n"
).generate(sink, attributes::unused, context);
).generate(sink, *etype, context);
}
} const event_argument_wrapper {};

View File

@ -559,7 +559,7 @@ struct native_convert_in_variable_generator
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
"var " << string << " = " << type << "_StructConversion.ToExternal(" << escape_keyword(param.param_name) << ");\n"
"var " << string << " = " << type << "_StructConversion.ToManaged(" << escape_keyword(param.param_name) << ");\n"
).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
}
else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
@ -898,7 +898,7 @@ struct convert_out_assign_generator
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << type << "_StructConversion.ToExternal(" << out_variable_name(param.param_name) << ");\n"
string << " = " << type << "_StructConversion.ToManaged(" << out_variable_name(param.param_name) << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
}
else if (param_is_acceptable(param, "Eina_Binbuf *", WANT_OWN, WANT_OUT)
@ -1002,7 +1002,7 @@ struct convert_in_ptr_assign_generator
if (param_should_use_in_var(param, true) && param.type.is_ptr && !param.type.has_own && helpers::need_struct_conversion(regular))
{
return as_generator(
string << " = " << type << "_StructConversion.ToExternal(" << in_variable_name(param.param_name) << ");\n"
string << " = " << type << "_StructConversion.ToManaged(" << in_variable_name(param.param_name) << ");\n"
).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type), context);
}
@ -1040,7 +1040,7 @@ struct convert_return_generator
else if (helpers::need_struct_conversion(regular))
{
return as_generator(
"return " << type << "_StructConversion.ToExternal(_ret_var);\n"
"return " << type << "_StructConversion.ToManaged(_ret_var);\n"
).generate(sink, ret_type, context);
}
else if (ret_type.c_type == "Eina_Binbuf *" || ret_type.c_type == "const Eina_Binbuf *")

View File

@ -56,6 +56,8 @@ struct struct_definition_generator
return false;
}
auto struct_name = binding_struct_name(struct_);
// Check whether this is an extern struct without declared fields in .eo file and generate a
// placeholder field if positive.
// Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to
@ -68,7 +70,6 @@ struct struct_definition_generator
else
{
// Constructor with default parameters for easy struct initialization
auto struct_name = binding_struct_name(struct_);
if(!as_generator(
scope_tab << "///<summary>Constructor for " << string << ".</summary>\n"
<< scope_tab << "public " << string << "(\n"
@ -81,6 +82,16 @@ struct struct_definition_generator
return false;
}
if(!as_generator(
"public static implicit operator " << struct_name << "(IntPtr ptr)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "var tmp = (" << struct_name << "_StructInternal)Marshal.PtrToStructure(ptr, typeof(" << struct_name << "_StructInternal));\n"
<< scope_tab << scope_tab << "return " << struct_name << "_StructConversion.ToManaged(tmp);\n"
<< scope_tab << "}\n"
).generate(sink, attributes::unused, context))
return false;
if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false;
return true;
@ -120,7 +131,8 @@ struct struct_internal_definition_generator
.generate(sink, nullptr, context))
return false;
}
else if (!as_generator(eolian_mono::marshall_annotation(false) << " public " << eolian_mono::marshall_type(false) << " " << string << ";\n")
else if (!as_generator(scope_tab << eolian_mono::marshall_annotation(false) << "\n"
<< scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n")
.generate(sink, std::make_tuple(field.type, field.type, field_name), context))
return false;
}
@ -142,7 +154,7 @@ struct struct_internal_definition_generator
scope_tab << "///<summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
<< scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "return " << string << "_StructConversion.ToExternal(struct_);\n"
<< scope_tab << scope_tab << "return " << string << "_StructConversion.ToManaged(struct_);\n"
<< scope_tab << "}\n"
<< scope_tab << "///<summary>Implicit conversion to the managed representation.</summary>\n"
<< scope_tab << "public static implicit operator " << string << "(" << string << " struct_)\n"
@ -315,7 +327,7 @@ struct to_external_field_convert_generator
else if (helpers::need_struct_conversion(regular))
{
if (!as_generator(
scope_tab << scope_tab << "_external_struct." << string << " = " << type << "_StructConversion.ToExternal(_internal_struct." << string << ");\n")
scope_tab << scope_tab << "_external_struct." << string << " = " << type << "_StructConversion.ToManaged(_internal_struct." << string << ");\n")
.generate(sink, std::make_tuple(field_name, field.type, field_name), context))
return false;
}
@ -406,7 +418,7 @@ struct struct_binding_conversion_functions_generator
// to external
if (!as_generator
(
scope_tab << "internal static " << string << " ToExternal(" << string << " _internal_struct)\n"
scope_tab << "internal static " << string << " ToManaged(" << string << " _internal_struct)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "var _external_struct = new " << string << "();\n\n"
)

View File

@ -148,6 +148,22 @@ class TestEoEvents
Test.AssertEquals(sent_struct.Fstring, received_struct.Fstring);
}
public static void event_with_struct_complex_payload()
{
var obj = new Dummy.TestObject();
Dummy.StructComplex received_struct = default(Dummy.StructComplex);
obj.EvtWithStructComplexEvt += (object sender, Dummy.TestObjectEvtWithStructComplexEvt_Args e) => {
received_struct = e.arg;
};
Dummy.StructComplex sent_struct = StructHelpers.structComplexWithValues();
obj.EmitEventWithStructComplex(sent_struct);
Test.AssertEquals(sent_struct.Fobj, received_struct.Fobj);
}
public static void event_in_init_callback()
{
int received = 0;

View File

@ -1577,6 +1577,12 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
}
}
emit_event_with_struct_complex {
params {
@in data: Dummy.StructComplex;
}
}
append_to_strbuf {
params {
@in buf: strbuf;
@ -1671,5 +1677,6 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
evt,with,obj @hot: Dummy.Test_Object;
evt,with,error @hot: Eina.Error;
evt,with,struct @hot: Dummy.StructSimple;
evt,with,struct,complex @hot: Dummy.StructComplex;
}
}

View File

@ -3754,6 +3754,10 @@ void _dummy_test_object_emit_event_with_struct(Eo *obj, EINA_UNUSED Dummy_Test_O
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_STRUCT, &data);
}
void _dummy_test_object_emit_event_with_struct_complex(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Dummy_StructComplex data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_STRUCT_COMPLEX, &data);
}
Efl_Object *_dummy_test_object_efl_part_part_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd, const char *name)
{