remove risky finalization code from Dispatcher, and use reference types
This commit is contained in:
Родитель
f64194cab4
Коммит
0a89e6f1f4
|
@ -112,6 +112,8 @@ namespace Python.Runtime
|
|||
|
||||
internal static NewReference ToPythonReference<T>(T value)
|
||||
=> NewReference.DangerousFromPointer(ToPython(value, typeof(T)));
|
||||
internal static NewReference ToPythonReference(object value, Type type)
|
||||
=> NewReference.DangerousFromPointer(ToPython(value, type));
|
||||
|
||||
private static readonly Func<object, bool> IsTransparentProxy = GetIsTransparentProxy();
|
||||
|
||||
|
|
|
@ -29,21 +29,6 @@ namespace Python.Runtime
|
|||
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.
|
||||
|
@ -224,41 +209,15 @@ namespace Python.Runtime
|
|||
|
||||
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();
|
||||
|
@ -280,26 +239,36 @@ namespace Python.Runtime
|
|||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
op = Runtime.PyObject_Call(target.Reference, pyargs, BorrowedReference.Null);
|
||||
}
|
||||
|
||||
IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero);
|
||||
Runtime.XDecref(pyargs);
|
||||
|
||||
if (op == IntPtr.Zero)
|
||||
if (op.IsNull())
|
||||
{
|
||||
throw PythonException.ThrowLastAsClrException();
|
||||
}
|
||||
|
||||
try
|
||||
using (op)
|
||||
{
|
||||
int byRefCount = pi.Count(parameterInfo => parameterInfo.ParameterType.IsByRef);
|
||||
if (byRefCount > 0)
|
||||
|
@ -339,7 +308,7 @@ namespace Python.Runtime
|
|||
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)");
|
||||
|
@ -352,7 +321,7 @@ namespace Python.Runtime
|
|||
{
|
||||
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)");
|
||||
|
@ -397,10 +366,6 @@ namespace Python.Runtime
|
|||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Runtime.XDecref(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ class DotNetFinder(importlib.abc.MetaPathFinder):
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -1013,6 +1013,8 @@ namespace Python.Runtime
|
|||
internal static NewReference PyObject_Type(BorrowedReference o)
|
||||
=> Delegates.PyObject_Type(o);
|
||||
|
||||
internal static string PyObject_GetTypeName(BorrowedReference op)
|
||||
=> PyObject_GetTypeName(op.DangerousGetAddress());
|
||||
internal static string PyObject_GetTypeName(IntPtr op)
|
||||
{
|
||||
IntPtr pyType = PyObject_TYPE(op);
|
||||
|
@ -1097,8 +1099,8 @@ namespace Python.Runtime
|
|||
|
||||
|
||||
internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw);
|
||||
internal static IntPtr PyObject_Call(BorrowedReference pointer, BorrowedReference args, BorrowedReference kw)
|
||||
=> Delegates.PyObject_Call(pointer.DangerousGetAddress(), args.DangerousGetAddress(), kw.DangerousGetAddressOrNull());
|
||||
internal static NewReference PyObject_Call(BorrowedReference pointer, BorrowedReference args, BorrowedReference kw)
|
||||
=> NewReference.DangerousFromPointer(Delegates.PyObject_Call(pointer.DangerousGetAddress(), args.DangerousGetAddress(), kw.DangerousGetAddressOrNull()));
|
||||
|
||||
|
||||
internal static NewReference PyObject_CallObject(BorrowedReference callable, BorrowedReference args) => Delegates.PyObject_CallObject(callable, args);
|
||||
|
|
Загрузка…
Ссылка в новой задаче