Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1f3fec7

Browse files
committed
Support ByRef arguments in event handlers
1 parent 5fd77b1 commit 1f3fec7

File tree

4 files changed

+60
-3
lines changed

4 files changed

+60
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ when .NET expects an integer [#1342][i1342]
4747
- Fixed issue when calling PythonException.Format where another exception would be raise for unnormalized exceptions
4848
- Made it possible to call `ToString`, `GetHashCode`, and `GetType` on inteface objects
4949
- Fixed objects returned by enumerating `PyObject` being disposed too soon
50-
- Incorrectly using a non-generic type with type parameters now produces a helpful Python error instead of throwing NullReferenceException
51-
- `import` may now raise errors with more detail than "No module named X"
50+
- Incorrectly using a non-generic type with type parameters now produces a helpful Python error instead of throwing NullReferenceException ([#1325][i1325])
51+
- `import` may now raise errors with more detail than "No module named X"
52+
- Fixed a crash when invoking a Python event handler for an event with a ByRef argument ([#1355][i1355])
5253

5354
### Removed
5455

src/runtime/delegatemanager.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,20 @@ private Type GetDispatcher(Type dtype)
118118
il.Emit(OpCodes.Ldloc_0);
119119
il.Emit(OpCodes.Ldarg_S, (byte)(c + 1));
120120

121+
if (t.IsByRef)
122+
{
123+
// The argument is a pointer. We must dereference the pointer to get the value or object it points to.
124+
t = t.GetElementType();
125+
if (t.IsValueType)
126+
{
127+
il.Emit(OpCodes.Ldobj, t);
128+
}
129+
else
130+
{
131+
il.Emit(OpCodes.Ldind_Ref);
132+
}
133+
}
134+
121135
if (t.IsValueType)
122136
{
123137
il.Emit(OpCodes.Box, t);

src/testing/eventtest.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ namespace Python.Test
77
/// </summary>
88
public delegate void EventHandlerTest(object sender, EventArgsTest e);
99

10+
public delegate void EventWithRefStringArgument(ref string data);
11+
public delegate void EventWithRefIntArgument(ref int data);
1012

11-
#pragma warning disable 67 // Unused events, these are only accessed from Python
13+
#pragma warning disable 67 // Unused events, these are only accessed from Python
1214
public class EventTest
1315
{
1416
public static event EventHandlerTest PublicStaticEvent;
@@ -27,6 +29,8 @@ public class EventTest
2729

2830
private event EventHandlerTest PrivateEvent;
2931

32+
public event EventWithRefStringArgument RefStringEvent;
33+
public event EventWithRefIntArgument RefIntEvent;
3034

3135
public static int s_value;
3236
public int value;
@@ -77,6 +81,15 @@ protected static void OnProtectedStaticEvent(EventArgsTest e)
7781
}
7882
}
7983

84+
public void OnRefStringEvent(string data)
85+
{
86+
RefStringEvent?.Invoke(ref data);
87+
}
88+
89+
public void OnRefIntEvent(int data)
90+
{
91+
RefIntEvent?.Invoke(ref data);
92+
}
8093

8194
public void GenericHandler(object sender, EventArgsTest e)
8295
{
@@ -88,6 +101,16 @@ public static void StaticHandler(object sender, EventArgsTest e)
88101
s_value = e.value;
89102
}
90103

104+
public void RefStringHandler(ref string data)
105+
{
106+
value = data.Length;
107+
}
108+
109+
public void RefIntHandler(ref int data)
110+
{
111+
value = data;
112+
}
113+
91114
public static void ShutUpCompiler()
92115
{
93116
// Quiet compiler warnings.

src/tests/test_event.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,25 @@ def handler(sender, args, dict_=dict_):
295295
ob.OnPublicEvent(EventArgsTest(20))
296296
assert dict_['value'] == 10
297297

298+
def test_byref_function_handler():
299+
"""Test function handlers with ByRef arguments."""
300+
ob = EventTest()
301+
302+
value = 10
303+
def handler(data):
304+
assert data == value
305+
ob.value = ob.value + 1
306+
307+
ob.RefIntEvent += ob.RefIntHandler
308+
ob.RefIntEvent += handler
309+
ob.OnRefIntEvent(value)
310+
assert ob.value == value + 1
311+
312+
ob.RefStringEvent += ob.RefStringHandler
313+
ob.RefStringEvent += handler
314+
value = 'This is the event data'
315+
ob.OnRefStringEvent(value)
316+
assert ob.value == len(value) + 1
298317

299318
def test_add_non_callable_handler():
300319
"""Test handling of attempts to add non-callable handlers."""

0 commit comments

Comments
 (0)