| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent dc3c818 commit 2ef6b50
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,7 +1,5 @@ | |||
| 1 | 1 | using System; | |
| 2 | 2 | using System.Collections.Generic; | |
| 3 | - using System.Diagnostics; | ||
| 4 | - using System.Runtime.InteropServices; | ||
| 5 | 3 | ||
| 6 | 4 | using NUnit.Framework; | |
| 7 | 5 | ||
@@ -100,6 +98,18 @@ public void SetAdHocAttributes_WhenExtraBasePresent() | |||
| 100 | 98 | int actual = scope.Eval<int>($"{nameof(instance)}.{nameof(Inherited.XProp)}"); | |
| 101 | 99 | Assert.AreEqual(expected: Inherited.X, actual); | |
| 102 | 100 | } | |
| 101 | + | ||
| 102 | + // https://github.com/pythonnet/pythonnet/issues/1476 | ||
| 103 | + [Test] | ||
| 104 | + public void BaseClearIsCalled() | ||
| 105 | + { | ||
| 106 | + using var scope = Py.CreateScope(); | ||
| 107 | + scope.Set("exn", new Exception("42")); | ||
| 108 | + var msg = scope.Eval("exn.args[0]"); | ||
| 109 | + Assert.AreEqual(2, msg.Refcount); | ||
| 110 | + scope.Set("exn", null); | ||
| 111 | + Assert.AreEqual(1, msg.Refcount); | ||
| 112 | + } | ||
| 103 | 113 | } | |
| 104 | 114 | ||
| 105 | 115 | class ExtraBaseTypeProvider : IPythonBaseTypeProvider | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,7 @@ | |||
| 1 | 1 | using System; | |
| 2 | 2 | using System.Collections; | |
| 3 | 3 | using System.Collections.Generic; | |
| 4 | + using System.Runtime.InteropServices; | ||
| 4 | 5 | ||
| 5 | 6 | namespace Python.Runtime | |
| 6 | 7 | { | |
@@ -365,11 +366,30 @@ public static int tp_clear(IntPtr ob) | |||
| 365 | 366 | if (!isTypeObject) | |
| 366 | 367 | { | |
| 367 | 368 | ClearObjectDict(ob); | |
| 369 | + | ||
| 370 | + int baseClearResult = BaseUnmanagedClear(ob); | ||
| 371 | + if (baseClearResult != 0) | ||
| 372 | + { | ||
| 373 | + return baseClearResult; | ||
| 374 | + } | ||
| 368 | 375 | } | |
| 369 | 376 | if (self is not null) self.tpHandle = IntPtr.Zero; | |
| 370 | 377 | return 0; | |
| 371 | 378 | } | |
| 372 | 379 | ||
| 380 | + static unsafe int BaseUnmanagedClear(IntPtr ob) | ||
| 381 | + { | ||
| 382 | + var type = Runtime.PyObject_TYPE(new BorrowedReference(ob)); | ||
| 383 | + var unmanagedBase = GetUnmanagedBaseType(type); | ||
| 384 | + var clearPtr = Marshal.ReadIntPtr(unmanagedBase.DangerousGetAddress(), TypeOffset.tp_clear); | ||
| 385 | + if (clearPtr == IntPtr.Zero) | ||
| 386 | + { | ||
| 387 | + return 0; | ||
| 388 | + } | ||
| 389 | + var clear = (delegate* unmanaged[Cdecl]<IntPtr, int>)clearPtr; | ||
| 390 | + return clear(ob); | ||
| 391 | + } | ||
| 392 | + | ||
| 373 | 393 | protected override void OnSave(InterDomainContext context) | |
| 374 | 394 | { | |
| 375 | 395 | base.OnSave(context); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -149,6 +149,16 @@ internal static bool IsManagedType(BorrowedReference type) | |||
| 149 | 149 | return (flags & TypeFlags.HasClrInstance) != 0; | |
| 150 | 150 | } | |
| 151 | 151 | ||
| 152 | + internal static BorrowedReference GetUnmanagedBaseType(BorrowedReference managedType) | ||
| 153 | + { | ||
| 154 | + Debug.Assert(managedType != null && IsManagedType(managedType)); | ||
| 155 | + do | ||
| 156 | + { | ||
| 157 | + managedType = PyType.GetBase(managedType); | ||
| 158 | + } while (IsManagedType(managedType)); | ||
| 159 | + return managedType; | ||
| 160 | + } | ||
| 161 | + | ||
| 152 | 162 | public bool IsClrMetaTypeInstance() | |
| 153 | 163 | { | |
| 154 | 164 | Debug.Assert(Runtime.PyCLRMetaType != IntPtr.Zero); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | #nullable enable | |
| 2 | 2 | using System; | |
| 3 | + using System.Diagnostics; | ||
| 3 | 4 | using System.Runtime.InteropServices; | |
| 4 | 5 | ||
| 5 | 6 | using Python.Runtime.Native; | |
@@ -60,6 +61,11 @@ public static bool IsType(PyObject value) | |||
| 60 | 61 | ||
| 61 | 62 | return Runtime.PyType_Check(value.obj); | |
| 62 | 63 | } | |
| 64 | + /// <summary>Checks if specified object is a Python type.</summary> | ||
| 65 | + internal static bool IsType(BorrowedReference value) | ||
| 66 | + { | ||
| 67 | + return Runtime.PyType_Check(value.DangerousGetAddress()); | ||
| 68 | + } | ||
| 63 | 69 | ||
| 64 | 70 | /// <summary> | |
| 65 | 71 | /// Gets <see cref="PyType"/>, which represents the specified CLR type. | |
@@ -78,10 +84,7 @@ internal static PyType Get(Type clrType) | |||
| 78 | 84 | ||
| 79 | 85 | internal BorrowedReference BaseReference | |
| 80 | 86 | { | |
| 81 | - get | ||
| 82 | - { | ||
| 83 | - return new(Marshal.ReadIntPtr(Handle, TypeOffset.tp_base)); | ||
| 84 | - } | ||
| 87 | + get => GetBase(Reference); | ||
| 85 | 88 | set | |
| 86 | 89 | { | |
| 87 | 90 | var old = BaseReference.DangerousGetAddressOrNull(); | |
@@ -100,6 +103,13 @@ internal IntPtr GetSlot(TypeSlotID slot) | |||
| 100 | 103 | return Exceptions.ErrorCheckIfNull(result); | |
| 101 | 104 | } | |
| 102 | 105 | ||
| 106 | + internal static BorrowedReference GetBase(BorrowedReference type) | ||
| 107 | + { | ||
| 108 | + Debug.Assert(IsType(type)); | ||
| 109 | + IntPtr basePtr = Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.tp_base); | ||
| 110 | + return new BorrowedReference(basePtr); | ||
| 111 | + } | ||
| 112 | + | ||
| 103 | 113 | private static IntPtr EnsureIsType(in StolenReference reference) | |
| 104 | 114 | { | |
| 105 | 115 | IntPtr address = reference.DangerousGetAddressOrNull(); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments