From 3b8e3ebfaafbaafcde2264c48ad61afd5c2e5170 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Tue, 14 May 2019 08:38:50 +0200 Subject: [PATCH] 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 --- src/bin/eolian_mono/eolian/mono/events.hh | 39 +++++++++++++++++++++++++--- src/tests/efl_mono/Events.cs | 27 +++++++++++++++++++ src/tests/efl_mono/dummy_test_object.eo | 37 ++++++++++++++++++++++++++ src/tests/efl_mono/libefl_mono_native_test.c | 16 +++++++++--- 4 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh index 56a22d7..b5e6e4a 100644 --- a/src/bin/eolian_mono/eolian/mono/events.hh +++ b/src/bin/eolian_mono/eolian/mono/events.hh @@ -45,11 +45,44 @@ struct unpack_event_args_visitor eina::optional name; std::function 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(" + arg + ")"; }} + , {"double", [&arg] { return "Eina.PrimitiveConversion.PointerToManaged(" + 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))"; }} diff --git a/src/tests/efl_mono/Events.cs b/src/tests/efl_mono/Events.cs index 32c87b2..70a49bf 100644 --- a/src/tests/efl_mono/Events.cs +++ b/src/tests/efl_mono/Events.cs @@ -100,6 +100,33 @@ class TestEoEvents Test.AssertEquals(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(); diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo index b5436a6..ad859c6 100644 --- a/src/tests/efl_mono/dummy_test_object.eo +++ b/src/tests/efl_mono/dummy_test_object.eo @@ -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); 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; + } } diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c index 0201a6a..c5850d6a 100644 --- a/src/tests/efl_mono/libefl_mono_native_test.c +++ b/src/tests/efl_mono/libefl_mono_native_test.c @@ -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) -- 2.7.4