Simplify `Dispatcher` by lostmsu · Pull Request #1559 · pythonnet/pythonnet · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/runtime/converter.cs
87 changes: 26 additions & 61 deletions src/runtime/delegatemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,6 @@ public DelegateManager()
dispatch = basetype.GetMethod("Dispatch");
}

/// <summary>
/// Given a true delegate instance, return the PyObject handle of the
/// Python object implementing the delegate (or IntPtr.Zero if the
/// delegate is not implemented in Python code.
/// </summary>
public IntPtr GetPythonHandle(Delegate d)
{
if (d?.Target is Dispatcher)
{
var disp = (Dispatcher)d.Target;
return disp.target;
}
return IntPtr.Zero;
}

/// <summary>
/// GetDispatcher is responsible for creating a class that provides
/// an appropriate managed callback method for a given delegate type.
Expand Down Expand Up @@ -224,41 +209,15 @@ A possible alternate strategy would be to create custom subclasses

public class Dispatcher
{
public IntPtr target;
public Type dtype;
private bool _disposed = false;
private bool _finalized = false;
readonly PyObject target;
readonly Type dtype;

public Dispatcher(IntPtr target, Type dtype)
{
Runtime.XIncref(target);
this.target = target;
this.target = new PyObject(new BorrowedReference(target));
this.dtype = dtype;
}

~Dispatcher()
{
if (_finalized || _disposed)
{
return;
}
_finalized = true;
Finalizer.Instance.AddFinalizedObject(ref target);
}

public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
Runtime.XDecref(target);
target = IntPtr.Zero;
dtype = null;
GC.SuppressFinalize(this);
}

public object Dispatch(object[] args)
{
IntPtr gs = PythonEngine.AcquireLock();
Expand All @@ -280,26 +239,36 @@ private object TrueDispatch(object[] args)
{
MethodInfo method = dtype.GetMethod("Invoke");
ParameterInfo[] pi = method.GetParameters();
IntPtr pyargs = Runtime.PyTuple_New(pi.Length);
Type rtype = method.ReturnType;

for (var i = 0; i < pi.Length; i++)
NewReference op;
using (var pyargs = NewReference.DangerousFromPointer(Runtime.PyTuple_New(pi.Length)))
{
// Here we own the reference to the Python value, and we
// give the ownership to the arg tuple.
IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType);
Runtime.PyTuple_SetItem(pyargs, i, arg);
}
for (var i = 0; i < pi.Length; i++)
{
// Here we own the reference to the Python value, and we
// give the ownership to the arg tuple.
var arg = Converter.ToPythonReference(args[i], pi[i].ParameterType);
if (arg.IsNull())
{
throw PythonException.ThrowLastAsClrException();
}
int res = Runtime.PyTuple_SetItem(pyargs, i, arg.Steal());
if (res != 0)
{
throw PythonException.ThrowLastAsClrException();
}
}

IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero);
Runtime.XDecref(pyargs);
op = Runtime.PyObject_Call(target.Reference, pyargs, BorrowedReference.Null);
}

if (op == IntPtr.Zero)
if (op.IsNull())
{
throw PythonException.ThrowLastAsClrException();
}

try
using (op)
{
int byRefCount = pi.Count(parameterInfo => parameterInfo.ParameterType.IsByRef);
if (byRefCount > 0)
Expand Down Expand Up @@ -339,7 +308,7 @@ private object TrueDispatch(object[] args)
Type t = pi[i].ParameterType;
if (t.IsByRef)
{
IntPtr item = Runtime.PyTuple_GetItem(op, index++);
BorrowedReference item = Runtime.PyTuple_GetItem(op, index++);
if (!Converter.ToManaged(item, t, out object newArg, true))
{
Exceptions.RaiseTypeError($"The Python function returned a tuple where element {i} was not {t.GetElementType()} (the out parameter type)");
Expand All @@ -352,7 +321,7 @@ private object TrueDispatch(object[] args)
{
return null;
}
IntPtr item0 = Runtime.PyTuple_GetItem(op, 0);
BorrowedReference item0 = Runtime.PyTuple_GetItem(op, 0);
if (!Converter.ToManaged(item0, rtype, out object result0, true))
{
Exceptions.RaiseTypeError($"The Python function returned a tuple where element 0 was not {rtype} (the return type)");
Expand Down Expand Up @@ -397,10 +366,6 @@ private object TrueDispatch(object[] args)

return result;
}
finally
{
Runtime.XDecref(op);
}
}
}
}
2 changes: 1 addition & 1 deletion src/runtime/importhook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static void SetupImportHook()
var mod_dict = Runtime.PyModule_GetDict(import_hook_module);
// reference not stolen due to overload incref'ing for us.
Runtime.PyTuple_SetItem(args, 1, mod_dict);
Runtime.PyObject_Call(exec, args, default);
Runtime.PyObject_Call(exec, args, default).Dispose();
// Set as a sub-module of clr.
if(Runtime.PyModule_AddObject(ClrModuleReference, "loader", import_hook_module.DangerousGetAddress()) != 0)
{
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/runtime.cs