X Tutup
namespace Python.Runtime { using System; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; /// /// Represents a reference to a Python object, that is tracked by Python's reference counting. /// [NonCopyable] ref struct NewReference { IntPtr pointer; /// Creates a pointing to the same object [DebuggerHidden] public NewReference(BorrowedReference reference, bool canBeNull = false) { var address = canBeNull ? reference.DangerousGetAddressOrNull() : reference.DangerousGetAddress(); #pragma warning disable CS0618 // Type or member is obsolete Runtime.XIncref(reference); #pragma warning restore CS0618 // Type or member is obsolete this.pointer = address; } /// Creates a pointing to the same object public NewReference(in NewReference reference, bool canBeNull = false) : this(reference.BorrowNullable(), canBeNull) { } /// /// Returns wrapper around this reference, which now owns /// the pointer. Sets the original reference to null, as it no longer owns it. /// public PyObject MoveToPyObject() { if (this.IsNull()) throw new NullReferenceException(); return new PyObject(this.StealNullable()); } /// /// Creates new instance of which now owns the pointer. /// Sets the original reference to null, as it no longer owns the pointer. /// public NewReference Move() { var result = DangerousFromPointer(this.DangerousGetAddress()); this.pointer = default; return result; } /// Moves ownership of this instance to unmanged pointer public IntPtr DangerousMoveToPointer() { if (this.IsNull()) throw new NullReferenceException(); var result = this.pointer; this.pointer = IntPtr.Zero; return result; } /// Moves ownership of this instance to unmanged pointer public IntPtr DangerousMoveToPointerOrNull() { var result = this.pointer; this.pointer = IntPtr.Zero; return result; } /// /// Returns wrapper around this reference, which now owns /// the pointer. Sets the original reference to null, as it no longer owns it. /// public PyObject? MoveToPyObjectOrNull() => this.IsNull() ? null : this.MoveToPyObject(); /// /// Call this method to move ownership of this reference to a Python C API function, /// that steals reference passed to it. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [DebuggerHidden] public StolenReference StealNullable() => StolenReference.TakeNullable(ref this.pointer); /// /// Call this method to move ownership of this reference to a Python C API function, /// that steals reference passed to it. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [DebuggerHidden] public StolenReference Steal() { if (this.IsNull()) throw new NullReferenceException(); return this.StealNullable(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [DebuggerHidden] public StolenReference StealOrThrow() { if (this.IsNull()) throw PythonException.ThrowLastAsClrException(); return this.StealNullable(); } /// /// Removes this reference to a Python object, and sets it to null. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { if (this.IsNull()) { return; } Runtime.XDecref(this.Steal()); } /// /// Creates from a raw pointer /// [Pure] public static NewReference DangerousFromPointer(IntPtr pointer) => new() { pointer = pointer}; [Pure] internal static IntPtr DangerousGetAddressOrNull(in NewReference reference) => reference.pointer; [Pure] internal static IntPtr DangerousGetAddress(in NewReference reference) => IsNull(reference) ? throw new NullReferenceException() : reference.pointer; [Pure] [DebuggerHidden] internal static bool IsNull(in NewReference reference) => reference.pointer == IntPtr.Zero; } /// /// These members can not be directly in type, /// because this is always passed by value, which we need to avoid. /// (note this in NewReference vs the usual this NewReference) /// static class NewReferenceExtensions { /// Gets a raw pointer to the Python object [Pure] [DebuggerHidden] public static IntPtr DangerousGetAddress(this in NewReference reference) => NewReference.DangerousGetAddress(reference); [Pure] [DebuggerHidden] public static bool IsNull(this in NewReference reference) => NewReference.IsNull(reference); [Pure] [DebuggerHidden] public static BorrowedReference BorrowNullable(this in NewReference reference) => new(NewReference.DangerousGetAddressOrNull(reference)); [Pure] [DebuggerHidden] public static BorrowedReference Borrow(this in NewReference reference) => reference.IsNull() ? throw new NullReferenceException() : reference.BorrowNullable(); [Pure] [DebuggerHidden] public static BorrowedReference BorrowOrThrow(this in NewReference reference) => reference.IsNull() ? throw PythonException.ThrowLastAsClrException() : reference.BorrowNullable(); } }
X Tutup