diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs
index 32369190c..4e05850c1 100644
--- a/src/embed_tests/TestRuntime.cs
+++ b/src/embed_tests/TestRuntime.cs
@@ -92,27 +92,29 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
{
Runtime.Runtime.Py_Initialize();
- // Create an instance of threading.Lock, which is one of the very few types that does not have the
- // TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
- var threading = Runtime.Runtime.PyImport_ImportModule("threading");
- Exceptions.ErrorCheck(threading);
- var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
- Exceptions.ErrorCheck(threadingDict);
- var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
- if (lockType.IsNull)
- throw new KeyNotFoundException("class 'Lock' was not found in 'threading'");
-
- var args = Runtime.Runtime.PyTuple_New(0);
- var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType.DangerousGetAddress(), args);
- Runtime.Runtime.XDecref(args);
- Exceptions.ErrorCheck(lockInstance);
-
- Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
- Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
-
- threading.Dispose();
-
- Runtime.Runtime.Py_Finalize();
+ try
+ {
+ // Create an instance of threading.Lock, which is one of the very few types that does not have the
+ // TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
+ using var threading = Runtime.Runtime.PyImport_ImportModule("threading");
+ Exceptions.ErrorCheck(threading);
+ var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
+ Exceptions.ErrorCheck(threadingDict);
+ var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
+ if (lockType.IsNull)
+ throw new PythonException();
+
+ using var args = NewReference.DangerousFromPointer(Runtime.Runtime.PyTuple_New(0));
+ using var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType, args);
+ Exceptions.ErrorCheck(lockInstance);
+
+ Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
+ Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
+ }
+ finally
+ {
+ Runtime.Runtime.Py_Finalize();
+ }
}
}
}
diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs
index 6ebf885a0..232dd8708 100644
--- a/src/runtime/runtime.cs
+++ b/src/runtime/runtime.cs
@@ -1009,6 +1009,11 @@ internal static string PyObject_GetTypeName(IntPtr op)
return Marshal.PtrToStringAnsi(ppName);
}
+ ///
+ /// Test whether the Python object is an iterable.
+ ///
+ internal static bool PyObject_IsIterable(BorrowedReference ob)
+ => PyObject_IsIterable(ob.DangerousGetAddress());
///
/// Test whether the Python object is an iterable.
///
@@ -1078,7 +1083,10 @@ internal static IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name)
internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw);
- internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args) => Delegates.PyObject_CallObject(pointer, args);
+ internal static NewReference PyObject_CallObject(BorrowedReference callable, BorrowedReference args) => Delegates.PyObject_CallObject(callable, args);
+ internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args)
+ => Delegates.PyObject_CallObject(new BorrowedReference(pointer), new BorrowedReference(args))
+ .DangerousMoveToPointerOrNull();
internal static int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid) => Delegates.PyObject_RichCompareBool(value1, value2, opid);
@@ -1880,6 +1888,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end)
//====================================================================
// Python iterator API
//====================================================================
+ internal static bool PyIter_Check(BorrowedReference ob) => PyIter_Check(ob.DangerousGetAddress());
internal static bool PyIter_Check(IntPtr pointer)
{
@@ -2317,7 +2326,7 @@ static Delegates()
PyObject_DelItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(_PythonDll));
PyObject_GetIter = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(_PythonDll));
PyObject_Call = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(_PythonDll));
- PyObject_CallObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(_PythonDll));
+ PyObject_CallObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(_PythonDll));
PyObject_RichCompareBool = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(_PythonDll));
PyObject_IsInstance = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(_PythonDll));
PyObject_IsSubclass = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(_PythonDll));
@@ -2616,7 +2625,7 @@ static Delegates()
internal static delegate* unmanaged[Cdecl] PyObject_DelItem { get; }
internal static delegate* unmanaged[Cdecl] PyObject_GetIter { get; }
internal static delegate* unmanaged[Cdecl] PyObject_Call { get; }
- internal static delegate* unmanaged[Cdecl] PyObject_CallObject { get; }
+ internal static delegate* unmanaged[Cdecl] PyObject_CallObject { get; }
internal static delegate* unmanaged[Cdecl] PyObject_RichCompareBool { get; }
internal static delegate* unmanaged[Cdecl] PyObject_IsInstance { get; }
internal static delegate* unmanaged[Cdecl] PyObject_IsSubclass { get; }