diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index 8b15213c3..f8b97b397 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -102,10 +102,7 @@ internal static IntPtr ToPython(IPythonDerivedType obj) // collected while Python still has a reference to it. if (Runtime.Refcount(self.pyHandle) == 1) { - -#if PYTHON_WITH_PYDEBUG - Runtime._Py_NewReference(self.pyHandle); -#endif + Runtime._Py_NewReference(self.ObjectReference); GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal); SetGCHandle(self.ObjectReference, self.TypeReference, gc); self.gcHandle.Free(); diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 2e10e9041..70b3d9eaa 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -525,6 +525,16 @@ internal static bool ToManagedValue(IntPtr value, Type obType, internal delegate bool TryConvertFromPythonDelegate(IntPtr pyObj, out object result); + internal static int ToInt32(BorrowedReference value) + { + nint num = Runtime.PyLong_AsSignedSize_t(value); + if (num == -1 && Exceptions.ErrorOccurred()) + { + throw new PythonException(); + } + return checked((int)num); + } + /// /// Convert a Python value to an instance of a primitive managed type. /// diff --git a/src/runtime/native/ABI.cs b/src/runtime/native/ABI.cs index 339919dee..e99fc33ab 100644 --- a/src/runtime/native/ABI.cs +++ b/src/runtime/native/ABI.cs @@ -7,6 +7,9 @@ namespace Python.Runtime.Native static class ABI { + public static int RefCountOffset { get; } = GetRefCountOffset(); + public static int ObjectHeadOffset => RefCountOffset; + internal static void Initialize(Version version, BorrowedReference pyType) { string offsetsClassSuffix = string.Format(CultureInfo.InvariantCulture, @@ -16,18 +19,34 @@ internal static void Initialize(Version version, BorrowedReference pyType) const string nativeTypeOffsetClassName = "Python.Runtime.NativeTypeOffset"; string className = "Python.Runtime.TypeOffset" + offsetsClassSuffix; + Type nativeOffsetsClass = thisAssembly.GetType(nativeTypeOffsetClassName, throwOnError: false); Type typeOffsetsClass = // Try platform native offsets first. It is only present when generated by setup.py - thisAssembly.GetType(nativeTypeOffsetClassName, throwOnError: false) - ?? thisAssembly.GetType(className, throwOnError: false); + nativeOffsetsClass ?? thisAssembly.GetType(className, throwOnError: false); if (typeOffsetsClass is null) { var types = thisAssembly.GetTypes().Select(type => type.Name).Where(name => name.StartsWith("TypeOffset")); string message = $"Searching for {className}, found {string.Join(",", types)}."; throw new NotSupportedException($"Python ABI v{version} is not supported: {message}"); } + var typeOffsets = (ITypeOffsets)Activator.CreateInstance(typeOffsetsClass); - TypeOffset.Use(typeOffsets); + TypeOffset.Use(typeOffsets, nativeOffsetsClass == null ? ObjectHeadOffset : 0); + } + + static unsafe int GetRefCountOffset() + { + IntPtr tempObject = Runtime.PyList_New(0); + IntPtr* tempPtr = (IntPtr*)tempObject; + int offset = 0; + while(tempPtr[offset] != (IntPtr)1) + { + offset++; + if (offset > 100) + throw new InvalidProgramException("PyObject_HEAD could not be found withing reasonable distance from the start of PyObject"); + } + Runtime.XDecref(tempObject); + return offset * IntPtr.Size; } } } diff --git a/src/runtime/native/TypeOffset.cs b/src/runtime/native/TypeOffset.cs index edbbe3b2c..4e5a726bc 100644 --- a/src/runtime/native/TypeOffset.cs +++ b/src/runtime/native/TypeOffset.cs @@ -75,7 +75,7 @@ static partial class TypeOffset internal static int tp_str { get; private set; } internal static int tp_traverse { get; private set; } - internal static void Use(ITypeOffsets offsets) + internal static void Use(ITypeOffsets offsets, int extraHeadOffset) { if (offsets is null) throw new ArgumentNullException(nameof(offsets)); @@ -87,6 +87,7 @@ internal static void Use(ITypeOffsets offsets) var sourceProperty = typeof(ITypeOffsets).GetProperty(offsetProperty.Name); int value = (int)sourceProperty.GetValue(offsets, null); + value += extraHeadOffset; offsetProperty.SetValue(obj: null, value: value, index: null); } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 1b1a7eccc..6ebf885a0 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -85,9 +85,9 @@ internal static Version PyVersion { using (var versionTuple = new PyTuple(PySys_GetObject("version_info"))) { - var major = versionTuple[0].As(); - var minor = versionTuple[1].As(); - var micro = versionTuple[2].As(); + var major = Converter.ToInt32(versionTuple[0].Reference); + var minor = Converter.ToInt32(versionTuple[1].Reference); + var micro = Converter.ToInt32(versionTuple[2].Reference); return new Version(major, minor, micro); } } @@ -198,15 +198,15 @@ private static void InitPyMembers() SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"), () => PyFalse = IntPtr.Zero); - SetPyMember(ref PyBoolType, PyObject_Type(PyTrue), + SetPyMemberTypeOf(ref PyBoolType, PyTrue, () => PyBoolType = IntPtr.Zero); - SetPyMember(ref PyNoneType, PyObject_Type(PyNone), + SetPyMemberTypeOf(ref PyNoneType, PyNone, () => PyNoneType = IntPtr.Zero); - SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType), + SetPyMemberTypeOf(ref PyTypeType, PyNoneType, () => PyTypeType = IntPtr.Zero); op = PyObject_GetAttrString(builtins, "len"); - SetPyMember(ref PyMethodType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyMethodType, op, () => PyMethodType = IntPtr.Zero); XDecref(op); @@ -215,7 +215,7 @@ private static void InitPyMembers() // // object.__init__ seems safe, though. op = PyObject_GetAttr(PyBaseObjectType, PyIdentifier.__init__); - SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyWrapperDescriptorType, op, () => PyWrapperDescriptorType = IntPtr.Zero); XDecref(op); @@ -226,47 +226,47 @@ private static void InitPyMembers() } op = PyString_FromString("string"); - SetPyMember(ref PyStringType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyStringType, op, () => PyStringType = IntPtr.Zero); XDecref(op); op = PyUnicode_FromString("unicode"); - SetPyMember(ref PyUnicodeType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyUnicodeType, op, () => PyUnicodeType = IntPtr.Zero); XDecref(op); op = EmptyPyBytes(); - SetPyMember(ref PyBytesType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyBytesType, op, () => PyBytesType = IntPtr.Zero); XDecref(op); op = PyTuple_New(0); - SetPyMember(ref PyTupleType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyTupleType, op, () => PyTupleType = IntPtr.Zero); XDecref(op); op = PyList_New(0); - SetPyMember(ref PyListType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyListType, op, () => PyListType = IntPtr.Zero); XDecref(op); op = PyDict_New(); - SetPyMember(ref PyDictType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyDictType, op, () => PyDictType = IntPtr.Zero); XDecref(op); op = PyInt_FromInt32(0); - SetPyMember(ref PyIntType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyIntType, op, () => PyIntType = IntPtr.Zero); XDecref(op); op = PyLong_FromLong(0); - SetPyMember(ref PyLongType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyLongType, op, () => PyLongType = IntPtr.Zero); XDecref(op); op = PyFloat_FromDouble(0); - SetPyMember(ref PyFloatType, PyObject_Type(op), + SetPyMemberTypeOf(ref PyFloatType, op, () => PyFloatType = IntPtr.Zero); XDecref(op); @@ -278,7 +278,8 @@ private static void InitPyMembers() _PyObject_NextNotImplemented = Get_PyObject_NextNotImplemented(); { using var sys = PyImport_ImportModule("sys"); - PyModuleType = PyObject_Type(sys.DangerousMoveToPointer()); + SetPyMemberTypeOf(ref PyModuleType, sys.DangerousGetAddress(), + () => PyModuleType = IntPtr.Zero); } } @@ -455,6 +456,12 @@ private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease) _pyRefs.Add(value, onRelease); } + private static void SetPyMemberTypeOf(ref IntPtr obj, IntPtr value, Action onRelease) + { + var type = PyObject_Type(new BorrowedReference(value)).DangerousMoveToPointer(); + SetPyMember(ref obj, type, onRelease); + } + private static void ResetPyMembers() { _pyRefs.Release(); @@ -761,16 +768,12 @@ internal static unsafe void XDecref(IntPtr op) [Pure] internal static unsafe long Refcount(IntPtr op) { -#if PYTHON_WITH_PYDEBUG - var p = (void*)(op + TypeOffset.ob_refcnt); -#else - var p = (void*)op; -#endif - if ((void*)0 == p) + if (op == IntPtr.Zero) { return 0; } - return Is32Bit ? (*(int*)p) : (*(long*)p); + var p = (nint*)(op + ABI.RefCountOffset); + return *p; } /// @@ -977,14 +980,9 @@ internal static unsafe IntPtr PyObject_TYPE(IntPtr op) { return IntPtr.Zero; } -#if PYTHON_WITH_PYDEBUG - var n = 3; -#else - var n = 1; -#endif - return Is32Bit - ? new IntPtr((void*)(*((uint*)p + n))) - : new IntPtr((void*)(*((ulong*)p + n))); + Debug.Assert(TypeOffset.ob_type > 0); + IntPtr* typePtr = (IntPtr*)(op + TypeOffset.ob_type); + return *typePtr; } internal static unsafe BorrowedReference PyObject_TYPE(BorrowedReference op) => new BorrowedReference(PyObject_TYPE(op.DangerousGetAddress())); @@ -1001,6 +999,9 @@ internal static IntPtr PyObject_Type(IntPtr op) return tp; } + internal static NewReference PyObject_Type(BorrowedReference o) + => Delegates.PyObject_Type(o); + internal static string PyObject_GetTypeName(IntPtr op) { IntPtr pyType = PyObject_TYPE(op); @@ -1145,10 +1146,11 @@ internal static IntPtr PyObject_Str(IntPtr pointer) internal static IntPtr PyObject_Dir(IntPtr pointer) => Delegates.PyObject_Dir(pointer); -#if PYTHON_WITH_PYDEBUG - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void _Py_NewReference(IntPtr ob); -#endif + internal static void _Py_NewReference(BorrowedReference ob) + { + if (Delegates._Py_NewReference != null) + Delegates._Py_NewReference(ob); + } //==================================================================== // Python buffer API @@ -1912,11 +1914,6 @@ internal static string PyModule_GetName(IntPtr module) internal static string PyModule_GetFilename(IntPtr module) => Delegates.PyModule_GetFilename(module).ToString(Encoding.UTF8); -#if PYTHON_WITH_PYDEBUG - [DllImport(_PythonDll, EntryPoint = "PyModule_Create2TraceRefs", CallingConvention = CallingConvention.Cdecl)] -#else - -#endif internal static IntPtr PyModule_Create2(IntPtr module, int apiver) => Delegates.PyModule_Create2(module, apiver); @@ -2331,6 +2328,7 @@ static Delegates() PyObject_Hash = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(_PythonDll)); PyObject_Repr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(_PythonDll)); PyObject_Str = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(_PythonDll)); + PyObject_Type = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Type), GetUnmanagedDll(_PythonDll)); PyObject_Dir = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(_PythonDll)); PyObject_GetBuffer = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetBuffer), GetUnmanagedDll(_PythonDll)); PyBuffer_Release = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_Release), GetUnmanagedDll(_PythonDll)); @@ -2466,7 +2464,14 @@ static Delegates() PyModule_GetName = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(_PythonDll)); PyModule_GetDict = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(_PythonDll)); PyModule_GetFilename = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(_PythonDll)); - PyModule_Create2 = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(_PythonDll)); + try + { + PyModule_Create2 = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(_PythonDll)); + } + catch (MissingMethodException) + { + PyModule_Create2 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyModule_Create2TraceRefs", GetUnmanagedDll(_PythonDll)); + } PyImport_Import = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(_PythonDll)); PyImport_ImportModule = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(_PythonDll)); PyImport_ReloadModule = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(_PythonDll)); @@ -2521,6 +2526,12 @@ static Delegates() PyThreadState_SetAsyncExcLLP64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyThreadState_SetAsyncExc", GetUnmanagedDll(_PythonDll)); PyThreadState_SetAsyncExcLP64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyThreadState_SetAsyncExc", GetUnmanagedDll(_PythonDll)); PyType_FromSpecWithBases = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_FromSpecWithBases), GetUnmanagedDll(PythonDLL)); + + try + { + _Py_NewReference = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_Py_NewReference), GetUnmanagedDll(_PythonDll)); + } + catch (MissingMethodException) { } } static global::System.IntPtr GetUnmanagedDll(string libraryName) @@ -2616,6 +2627,7 @@ static Delegates() internal static delegate* unmanaged[Cdecl] PyObject_Hash { get; } internal static delegate* unmanaged[Cdecl] PyObject_Repr { get; } internal static delegate* unmanaged[Cdecl] PyObject_Str { get; } + internal static delegate* unmanaged[Cdecl] PyObject_Type { get; } internal static delegate* unmanaged[Cdecl] PyObject_Dir { get; } internal static delegate* unmanaged[Cdecl] PyObject_GetBuffer { get; } internal static delegate* unmanaged[Cdecl] PyBuffer_Release { get; } @@ -2799,6 +2811,7 @@ static Delegates() internal static delegate* unmanaged[Cdecl] PyThreadState_SetAsyncExcLP64 { get; } internal static delegate* unmanaged[Cdecl] PyObject_GenericGetDict { get; } internal static delegate* unmanaged[Cdecl] PyType_FromSpecWithBases { get; } + internal static delegate* unmanaged[Cdecl] _Py_NewReference { get; } } } pFad - Phonifier reborn Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved. Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages. Alternative Proxies:Alternative ProxypFad ProxypFad v3 ProxypFad v4 Proxy
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy