csharp: Fix event marshalling for value types

Summary:
It was wrongly assuming value types were passed by value.

As stated in the documentation, all arguments are passed with a single
level of indirection.

Fixes T7957

Reviewers: woohyun, felipealmeida, vitor.sousa, segfaultxavi

Reviewed By: segfaultxavi

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T7957

Differential Revision: https://phab.enlightenment.org/D8889
This commit is contained in:
Lauro Moura 2019-05-14 08:38:50 +02:00 committed by Xavi Artigas
parent b3d7e9128b
commit f93eb3fc04
4 changed files with 113 additions and 6 deletions

View File

@ -45,11 +45,44 @@ struct unpack_event_args_visitor
eina::optional<std::string> name;
std::function<std::string()> function;
}
/// Sizes taken from https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sizeof
const match_table [] =
{
{"bool", [&arg] { return arg + " != IntPtr.Zero"; }}
, {"int", [&arg] { return arg + ".ToInt32()"; }}
, {"uint", [&arg] { return "(uint)" + arg + ".ToInt32()";}}
{"bool", [&arg] { return "Marshal.ReadByte(" + arg + ") != 0"; }}
, {"ubyte", [&arg] { return "Marshal.ReadByte(" + arg + ")"; }}
, {"byte", [&arg] { return "(sbyte) Marshal.ReadByte(" + arg + ")"; }}
, {"char", [&arg] { return "(char) Marshal.ReadByte(" + arg + ")"; }}
, {"short", [&arg] { return "Marshal.ReadInt16(" + arg + ")"; }}
, {"ushort", [&arg] { return "(ushort) Marshal.ReadInt16(" + arg + ")"; }}
, {"int", [&arg] { return "Marshal.ReadInt32(" + arg + ")"; }}
, {"uint", [&arg] { return "(uint) Marshal.ReadInt32(" + arg + ")"; }}
, {"long", [&arg] { return "Marshal.ReadInt64(" + arg + ")"; }}
, {"ulong", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }}
, {"llong", [&arg] { return "(long) Marshal.ReadInt64(" + arg + ")"; }}
, {"ullong", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }}
, {"int8", [&arg] { return "(sbyte)Marshal.ReadByte(" + arg + ")"; }}
, {"uint8", [&arg] { return "Marshal.ReadByte(" + arg + ")"; }}
, {"int16", [&arg] { return "Marshal.ReadInt16(" + arg + ")"; }}
, {"uint16", [&arg] { return "(ushort)Marshal.ReadInt16(" + arg + ")"; }}
, {"int32", [&arg] { return "Marshal.ReadInt32(" + arg + ")"; }}
, {"uint32", [&arg] { return "(uint) Marshal.ReadInt32(" + arg + ")"; }}
// We don't support int128 as csharp has no similar datatype.
, {"int64", [&arg] { return "Marshal.ReadInt64(" + arg + ")"; }}
, {"uint64", [&arg] { return "(ulong) Marshal.ReadInt64(" + arg + ")"; }}
, {"float", [&arg] { return "Eina.PrimitiveConversion.PointerToManaged<float>(" + arg + ")"; }}
, {"double", [&arg] { return "Eina.PrimitiveConversion.PointerToManaged<double>(" + arg + ")"; }}
, {"string", [&arg] { return "Eina.StringConversion.NativeUtf8ToManagedString(" + arg + ")"; }}
, {"stringshare", [&arg] { return "Eina.StringConversion.NativeUtf8ToManagedString(" + arg + ")"; }}
, {"Eina.Error", [&arg] { return "(Eina.Error)Marshal.PtrToStructure(" + arg + ", typeof(Eina.Error))"; }}

View File

@ -100,6 +100,33 @@ class TestEoEvents
Test.AssertEquals<uint>(0xbeef, received_uint);
}
public static void event_with_float_payload()
{
var obj = new Dummy.TestObject();
float received_float = 0;
obj.EvtWithFloatEvt += (object sender, Dummy.TestObjectEvtWithFloatEvt_Args e) => {
received_float = e.arg;
};
obj.EmitEventWithFloat(3.14f);
Test.AssertAlmostEquals(3.14f, received_float);
}
public static void event_with_double_payload()
{
var obj = new Dummy.TestObject();
double received_double = 0;
double reference = float.MaxValue + 42;
obj.EvtWithDoubleEvt += (object sender, Dummy.TestObjectEvtWithDoubleEvt_Args e) => {
received_double = e.arg;
};
obj.EmitEventWithDouble(reference);
Test.AssertAlmostEquals(reference, received_double);
}
public static void event_with_object_payload()
{
var obj = new Dummy.TestObject();

View File

@ -1284,6 +1284,16 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
@in data: uint;
}
}
emit_event_with_float {
params {
@in data: float;
}
}
emit_event_with_double {
params {
@in data: double;
}
}
emit_event_with_obj {
params {
@in data: Dummy.Test_Object;
@ -1422,11 +1432,38 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
evt,with,bool: bool;
evt,with,int @hot: int;
evt,with,uint @hot: uint;
evt,with,float @hot: float;
evt,with,double @hot: double;
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;
evt,with,array @hot: const(array<string>);
evt_with,under @hot: void;
// Extra events to test generation, but not invocation
evt,with,byte: byte;
evt,with,ubyte: ubyte;
evt,with,char: char;
evt,with,short: short;
evt,with,ushort: ushort;
evt,with,llong: llong;
evt,with,ullong: ullong;
evt,with,int8 @hot: int8;
evt,with,uint8 @hot: uint8;
evt,with,int16 @hot: int16;
evt,with,uint16 @hot: uint16;
evt,with,int32 @hot: int32;
evt,with,uint32 @hot: uint32;
evt,with,int64 @hot: int64;
evt,with,uint64 @hot: uint64;
}
}

View File

@ -3782,17 +3782,27 @@ void _dummy_test_object_emit_event_with_string(Eo *obj, EINA_UNUSED Dummy_Test_O
void _dummy_test_object_emit_event_with_bool(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eina_Bool data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_BOOL, (void *) (uintptr_t) data);
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_BOOL, &data);
}
void _dummy_test_object_emit_event_with_int(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, int data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_INT, (void *) (uintptr_t) data);
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_INT, &data);
}
void _dummy_test_object_emit_event_with_uint(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, unsigned int data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_UINT, (void *) (uintptr_t) data);
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_UINT, &data);
}
void _dummy_test_object_emit_event_with_float(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, float data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_FLOAT, &data);
}
void _dummy_test_object_emit_event_with_double(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, double data)
{
efl_event_callback_legacy_call(obj, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_DOUBLE, &data);
}
void _dummy_test_object_emit_event_with_obj(Eo *obj, EINA_UNUSED Dummy_Test_Object_Data *pd, Eo *data)