X Tutup
using System.Reflection.Emit; using System; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; using System.Collections.Generic; using Python.Runtime.Native; using Python.Runtime.Platform; using System.Linq; namespace Python.Runtime { /// /// Encapsulates the low-level Python C API. Note that it is /// the responsibility of the caller to have acquired the GIL /// before calling any of these methods. /// public class Runtime { public static int UCS => _UCS; internal static readonly int _UCS = PyUnicode_GetMax() <= 0xFFFF ? 2 : 4; #if PYTHON36 const string _minor = "6"; #elif PYTHON37 const string _minor = "7"; #elif PYTHON38 const string _minor = "8"; #elif PYTHON39 const string _minor = "9"; #else #error You must define one of PYTHON36 to PYTHON39 #endif #if WINDOWS internal const string dllBase = "python3" + _minor; #else internal const string dllBase = "python3." + _minor; #endif #if PYTHON_WITH_PYDEBUG internal const string dllWithPyDebug = "d"; #else internal const string dllWithPyDebug = ""; #endif #if PYTHON_WITH_PYMALLOC internal const string dllWithPyMalloc = "m"; #else internal const string dllWithPyMalloc = ""; #endif // C# compiler copies constants to the assemblies that references this library. // We needs to replace all public constants to static readonly fields to allow // binary substitution of different Python.Runtime.dll builds in a target application. public static readonly string PythonDLL = _PythonDll; #if PYTHON_WITHOUT_ENABLE_SHARED && !NETSTANDARD internal const string _PythonDll = "__Internal"; #else internal const string _PythonDll = dllBase + dllWithPyDebug + dllWithPyMalloc; #endif // set to true when python is finalizing internal static object IsFinalizingLock = new object(); internal static bool IsFinalizing; private static bool _isInitialized = false; internal static readonly bool Is32Bit = IntPtr.Size == 4; // .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) internal static bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; internal static Version InteropVersion { get; } = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; public static int MainManagedThreadId { get; private set; } /// /// Encoding to use to convert Unicode to/from Managed to Native /// internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32; public static ShutdownMode ShutdownMode { get; internal set; } private static PyReferenceCollection _pyRefs = new PyReferenceCollection(); internal static Version PyVersion { get { using (var versionTuple = new PyTuple(PySys_GetObject("version_info"))) { var major = versionTuple[0].As(); var minor = versionTuple[1].As(); var micro = versionTuple[2].As(); return new Version(major, minor, micro); } } } /// /// Initialize the runtime... /// /// Always call this method from the Main thread. After the /// first call to this method, the main thread has acquired the GIL. internal static void Initialize(bool initSigs = false, ShutdownMode mode = ShutdownMode.Default) { if (_isInitialized) { return; } _isInitialized = true; if (mode == ShutdownMode.Default) { mode = GetDefaultShutdownMode(); } ShutdownMode = mode; if (Py_IsInitialized() == 0) { Py_InitializeEx(initSigs ? 1 : 0); if (PyEval_ThreadsInitialized() == 0) { PyEval_InitThreads(); } // XXX: Reload mode may reduct to Soft mode, // so even on Reload mode it still needs to save the RuntimeState if (mode == ShutdownMode.Soft || mode == ShutdownMode.Reload) { RuntimeState.Save(); } } else { // If we're coming back from a domain reload or a soft shutdown, // we have previously released the thread state. Restore the main // thread state here. PyGILState_Ensure(); } MainManagedThreadId = Thread.CurrentThread.ManagedThreadId; IsFinalizing = false; InternString.Initialize(); InitPyMembers(); ABI.Initialize(PyVersion, pyType: new BorrowedReference(PyTypeType)); GenericUtil.Reset(); PyScopeManager.Reset(); ClassManager.Reset(); ClassDerivedObject.Reset(); TypeManager.Initialize(); // Initialize modules that depend on the runtime class. AssemblyManager.Initialize(); OperatorMethod.Initialize(); if (mode == ShutdownMode.Reload && RuntimeData.HasStashData()) { RuntimeData.RestoreRuntimeData(); } else { PyCLRMetaType = MetaType.Initialize(); // Steal a reference ImportHook.Initialize(); } Exceptions.Initialize(); // Need to add the runtime directory to sys.path so that we // can find built-in assemblies like System.Data, et. al. string rtdir = RuntimeEnvironment.GetRuntimeDirectory(); IntPtr path = PySys_GetObject("path").DangerousGetAddress(); IntPtr item = PyString_FromString(rtdir); if (PySequence_Contains(path, item) == 0) { PyList_Append(new BorrowedReference(path), item); } XDecref(item); AssemblyManager.UpdatePath(); } private static void InitPyMembers() { IntPtr op; { var builtins = GetBuiltins(); SetPyMember(ref PyNotImplemented, PyObject_GetAttrString(builtins, "NotImplemented"), () => PyNotImplemented = IntPtr.Zero); SetPyMember(ref PyBaseObjectType, PyObject_GetAttrString(builtins, "object"), () => PyBaseObjectType = IntPtr.Zero); SetPyMember(ref PyNone, PyObject_GetAttrString(builtins, "None"), () => PyNone = IntPtr.Zero); SetPyMember(ref PyTrue, PyObject_GetAttrString(builtins, "True"), () => PyTrue = IntPtr.Zero); SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"), () => PyFalse = IntPtr.Zero); SetPyMember(ref PyBoolType, PyObject_Type(PyTrue), () => PyBoolType = IntPtr.Zero); SetPyMember(ref PyNoneType, PyObject_Type(PyNone), () => PyNoneType = IntPtr.Zero); SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType), () => PyTypeType = IntPtr.Zero); op = PyObject_GetAttrString(builtins, "len"); SetPyMember(ref PyMethodType, PyObject_Type(op), () => PyMethodType = IntPtr.Zero); XDecref(op); // For some arcane reason, builtins.__dict__.__setitem__ is *not* // a wrapper_descriptor, even though dict.__setitem__ is. // // object.__init__ seems safe, though. op = PyObject_GetAttr(PyBaseObjectType, PyIdentifier.__init__); SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op), () => PyWrapperDescriptorType = IntPtr.Zero); XDecref(op); SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"), () => PySuper_Type = IntPtr.Zero); XDecref(builtins); } op = PyString_FromString("string"); SetPyMember(ref PyStringType, PyObject_Type(op), () => PyStringType = IntPtr.Zero); XDecref(op); op = PyUnicode_FromString("unicode"); SetPyMember(ref PyUnicodeType, PyObject_Type(op), () => PyUnicodeType = IntPtr.Zero); XDecref(op); op = PyBytes_FromString("bytes"); SetPyMember(ref PyBytesType, PyObject_Type(op), () => PyBytesType = IntPtr.Zero); XDecref(op); op = PyTuple_New(0); SetPyMember(ref PyTupleType, PyObject_Type(op), () => PyTupleType = IntPtr.Zero); XDecref(op); op = PyList_New(0); SetPyMember(ref PyListType, PyObject_Type(op), () => PyListType = IntPtr.Zero); XDecref(op); op = PyDict_New(); SetPyMember(ref PyDictType, PyObject_Type(op), () => PyDictType = IntPtr.Zero); XDecref(op); op = PyInt_FromInt32(0); SetPyMember(ref PyIntType, PyObject_Type(op), () => PyIntType = IntPtr.Zero); XDecref(op); op = PyLong_FromLong(0); SetPyMember(ref PyLongType, PyObject_Type(op), () => PyLongType = IntPtr.Zero); XDecref(op); op = PyFloat_FromDouble(0); SetPyMember(ref PyFloatType, PyObject_Type(op), () => PyFloatType = IntPtr.Zero); XDecref(op); PyClassType = IntPtr.Zero; PyInstanceType = IntPtr.Zero; Error = new IntPtr(-1); _PyObject_NextNotImplemented = Get_PyObject_NextNotImplemented(); { IntPtr sys = PyImport_ImportModule("sys"); PyModuleType = PyObject_Type(sys); XDecref(sys); } } private static IntPtr Get_PyObject_NextNotImplemented() { IntPtr pyType = SlotHelper.CreateObjectType(); IntPtr iternext = Marshal.ReadIntPtr(pyType, TypeOffset.tp_iternext); Runtime.XDecref(pyType); return iternext; } /// /// Tries to downgrade the shutdown mode, if possible. /// The only possibles downgrades are: /// Soft -> Normal /// Reload -> Soft /// Reload -> Normal /// /// The desired shutdown mode /// The `mode` parameter if the downgrade is supported, the ShutdownMode /// set at initialization otherwise. static ShutdownMode TryDowngradeShutdown(ShutdownMode mode) { if ( mode == Runtime.ShutdownMode || mode == ShutdownMode.Normal || (mode == ShutdownMode.Soft && Runtime.ShutdownMode == ShutdownMode.Reload) ) { return mode; } else // we can't downgrade { return Runtime.ShutdownMode; } } internal static void Shutdown(ShutdownMode mode) { if (Py_IsInitialized() == 0 || !_isInitialized) { return; } _isInitialized = false; // If the shutdown mode specified is not the the same as the one specified // during Initialization, we need to validate it; we can only downgrade, // not upgrade the shutdown mode. mode = TryDowngradeShutdown(mode); var state = PyGILState_Ensure(); if (mode == ShutdownMode.Soft) { RunExitFuncs(); } if (mode == ShutdownMode.Reload) { RuntimeData.Stash(); } AssemblyManager.Shutdown(); OperatorMethod.Shutdown(); ImportHook.Shutdown(); ClearClrModules(); RemoveClrRootModule(); MoveClrInstancesOnwershipToPython(); ClassManager.DisposePythonWrappersForClrTypes(); TypeManager.RemoveTypes(); MetaType.Release(); PyCLRMetaType = IntPtr.Zero; Exceptions.Shutdown(); Finalizer.Shutdown(); InternString.Shutdown(); if (mode != ShutdownMode.Normal) { PyGC_Collect(); if (mode == ShutdownMode.Soft) { RuntimeState.Restore(); } ResetPyMembers(); GC.Collect(); try { GC.WaitForFullGCComplete(); } catch (NotImplementedException) { // Some clr runtime didn't implement GC.WaitForFullGCComplete yet. } GC.WaitForPendingFinalizers(); PyGILState_Release(state); // Then release the GIL for good, if there is somehting to release // Use the unchecked version as the checked version calls `abort()` // if the current state is NULL. if (_PyThreadState_UncheckedGet() != IntPtr.Zero) { PyEval_SaveThread(); } } else { ResetPyMembers(); Py_Finalize(); } } internal static void Shutdown() { var mode = ShutdownMode; Shutdown(mode); } internal static ShutdownMode GetDefaultShutdownMode() { string modeEvn = Environment.GetEnvironmentVariable("PYTHONNET_SHUTDOWN_MODE"); if (modeEvn == null) { return ShutdownMode.Normal; } ShutdownMode mode; if (Enum.TryParse(modeEvn, true, out mode)) { return mode; } return ShutdownMode.Normal; } // called *without* the GIL acquired by clr._AtExit internal static int AtExit() { lock (IsFinalizingLock) { IsFinalizing = true; } return 0; } private static void RunExitFuncs() { PyObject atexit; try { atexit = Py.Import("atexit"); } catch (PythonException e) { if (!e.IsMatches(Exceptions.ImportError)) { throw; } e.Dispose(); // The runtime may not provided `atexit` module. return; } using (atexit) { try { atexit.InvokeMethod("_run_exitfuncs").Dispose(); } catch (PythonException e) { Console.Error.WriteLine(e); e.Dispose(); } } } private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease) { // XXX: For current usages, value should not be null. PythonException.ThrowIfIsNull(value); obj = value; _pyRefs.Add(value, onRelease); } private static void ResetPyMembers() { _pyRefs.Release(); } private static void ClearClrModules() { var modules = PyImport_GetModuleDict(); var items = PyDict_Items(modules); long length = PyList_Size(items); for (long i = 0; i < length; i++) { var item = PyList_GetItem(items, i); var name = PyTuple_GetItem(item.DangerousGetAddress(), 0); var module = PyTuple_GetItem(item.DangerousGetAddress(), 1); if (ManagedType.IsManagedType(module)) { PyDict_DelItem(modules, name); } } items.Dispose(); } private static void RemoveClrRootModule() { var modules = PyImport_GetModuleDict(); PyDictTryDelItem(modules, "clr"); PyDictTryDelItem(modules, "clr._extra"); } private static void PyDictTryDelItem(IntPtr dict, string key) { if (PyDict_DelItemString(dict, key) == 0) { return; } if (!PythonException.Matches(Exceptions.KeyError)) { throw new PythonException(); } PyErr_Clear(); } private static void MoveClrInstancesOnwershipToPython() { var objs = ManagedType.GetManagedObjects(); var copyObjs = objs.ToArray(); foreach (var entry in copyObjs) { ManagedType obj = entry.Key; if (!objs.ContainsKey(obj)) { System.Diagnostics.Debug.Assert(obj.gcHandle == default); continue; } if (entry.Value == ManagedType.TrackTypes.Extension) { obj.CallTypeClear(); // obj's tp_type will degenerate to a pure Python type after TypeManager.RemoveTypes(), // thus just be safe to give it back to GC chain. if (!_PyObject_GC_IS_TRACKED(obj.pyHandle)) { PyObject_GC_Track(obj.pyHandle); } } if (obj.gcHandle.IsAllocated) { obj.gcHandle.Free(); } obj.gcHandle = default; } ManagedType.ClearTrackedObjects(); } internal static IntPtr PyBaseObjectType; internal static IntPtr PyModuleType; internal static IntPtr PyClassType; internal static IntPtr PyInstanceType; internal static IntPtr PySuper_Type; internal static IntPtr PyCLRMetaType; internal static IntPtr PyMethodType; internal static IntPtr PyWrapperDescriptorType; internal static IntPtr PyUnicodeType; internal static IntPtr PyStringType; internal static IntPtr PyTupleType; internal static IntPtr PyListType; internal static IntPtr PyDictType; internal static IntPtr PyIntType; internal static IntPtr PyLongType; internal static IntPtr PyFloatType; internal static IntPtr PyBoolType; internal static IntPtr PyNoneType; internal static IntPtr PyTypeType; internal static IntPtr Py_NoSiteFlag; internal static IntPtr PyBytesType; internal static IntPtr _PyObject_NextNotImplemented; internal static IntPtr PyNotImplemented; internal const int Py_LT = 0; internal const int Py_LE = 1; internal const int Py_EQ = 2; internal const int Py_NE = 3; internal const int Py_GT = 4; internal const int Py_GE = 5; internal static IntPtr PyTrue; internal static IntPtr PyFalse; internal static IntPtr PyNone; internal static IntPtr Error; public static PyObject None { get { var none = Runtime.PyNone; Runtime.XIncref(none); return new PyObject(none); } } /// /// Check if any Python Exceptions occurred. /// If any exist throw new PythonException. /// /// /// Can be used instead of `obj == IntPtr.Zero` for example. /// internal static void CheckExceptionOccurred() { if (PyErr_Occurred() != IntPtr.Zero) { throw new PythonException(); } } internal static IntPtr ExtendTuple(IntPtr t, params IntPtr[] args) { var size = PyTuple_Size(t); int add = args.Length; IntPtr item; IntPtr items = PyTuple_New(size + add); for (var i = 0; i < size; i++) { item = PyTuple_GetItem(t, i); XIncref(item); PyTuple_SetItem(items, i, item); } for (var n = 0; n < add; n++) { item = args[n]; XIncref(item); PyTuple_SetItem(items, size + n, item); } return items; } internal static Type[] PythonArgsToTypeArray(IntPtr arg) { return PythonArgsToTypeArray(arg, false); } internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) { // Given a PyObject * that is either a single type object or a // tuple of (managed or unmanaged) type objects, return a Type[] // containing the CLR Type objects that map to those types. IntPtr args = arg; var free = false; if (!PyTuple_Check(arg)) { args = PyTuple_New(1); XIncref(arg); PyTuple_SetItem(args, 0, arg); free = true; } var n = PyTuple_Size(args); var types = new Type[n]; Type t = null; for (var i = 0; i < n; i++) { IntPtr op = PyTuple_GetItem(args, i); if (mangleObjects && (!PyType_Check(op))) { op = PyObject_TYPE(op); } ManagedType mt = ManagedType.GetManagedObject(op); if (mt is ClassBase) { MaybeType _type = ((ClassBase)mt).type; t = _type.Valid ? _type.Value : null; } else if (mt is CLRObject) { object inst = ((CLRObject)mt).inst; if (inst is Type) { t = inst as Type; } } else { t = Converter.GetTypeByAlias(op); } if (t == null) { types = null; break; } types[i] = t; } if (free) { XDecref(args); } return types; } /// /// Managed exports of the Python C API. Where appropriate, we do /// some optimization to avoid managed <--> unmanaged transitions /// (mostly for heavily used methods). /// internal static unsafe void XIncref(IntPtr op) { #if !CUSTOM_INCDEC_REF Py_IncRef(op); return; #else var p = (void*)op; if ((void*)0 != p) { if (Is32Bit) { (*(int*)p)++; } else { (*(long*)p)++; } } #endif } /// /// Increase Python's ref counter for the given object, and get the object back. /// internal static IntPtr SelfIncRef(IntPtr op) { XIncref(op); return op; } internal static unsafe void XDecref(IntPtr op) { #if !CUSTOM_INCDEC_REF Py_DecRef(op); return; #else var p = (void*)op; if ((void*)0 != p) { if (Is32Bit) { --(*(int*)p); } else { --(*(long*)p); } if ((*(int*)p) == 0) { // PyObject_HEAD: struct _typeobject *ob_type void* t = Is32Bit ? (void*)(*((uint*)p + 1)) : (void*)(*((ulong*)p + 1)); // PyTypeObject: destructor tp_dealloc void* f = Is32Bit ? (void*)(*((uint*)t + 6)) : (void*)(*((ulong*)t + 6)); if ((void*)0 == f) { return; } NativeCall.Void_Call_1(new IntPtr(f), op); } } #endif } [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) { return 0; } return Is32Bit ? (*(int*)p) : (*(long*)p); } /// /// Export of Macro Py_XIncRef. Use XIncref instead. /// Limit this function usage for Testing and Py_Debug builds /// /// PyObject Ptr [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_IncRef(IntPtr ob); /// /// Export of Macro Py_XDecRef. Use XDecref instead. /// Limit this function usage for Testing and Py_Debug builds /// /// PyObject Ptr [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_DecRef(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_Initialize(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_InitializeEx(int initsigs); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_IsInitialized(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_Finalize(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_NewInterpreter(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_EndInterpreter(IntPtr threadState); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyThreadState_New(IntPtr istate); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyThreadState_Get(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr _PyThreadState_UncheckedGet(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyThread_get_key_value(IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyThread_get_thread_ident(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyThread_set_key_value(IntPtr key, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyThreadState_Swap(IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyGILState_Ensure(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyGILState_Release(IntPtr gs); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyGILState_GetThisThreadState(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] public static extern int Py_Main( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv ); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_InitThreads(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyEval_ThreadsInitialized(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_AcquireLock(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_ReleaseLock(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_AcquireThread(IntPtr tstate); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_ReleaseThread(IntPtr tstate); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyEval_SaveThread(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyEval_RestoreThread(IntPtr tstate); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyEval_GetBuiltins(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyEval_GetGlobals(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyEval_GetLocals(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetProgramName(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_SetProgramName(IntPtr name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetPythonHome(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_SetPythonHome(IntPtr home); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetPath(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void Py_SetPath(IntPtr home); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetVersion(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetPlatform(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetCopyright(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetCompiler(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_GetBuildInfo(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyRun_SimpleString(string code); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern NewReference PyRun_String([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string code, RunFlagType st, IntPtr globals, IntPtr locals); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals); /// /// Return value: New reference. /// This is a simplified interface to Py_CompileStringFlags() below, leaving flags set to NULL. /// internal static IntPtr Py_CompileString(string str, string file, int start) { return Py_CompileStringFlags(str, file, start, IntPtr.Zero); } /// /// Return value: New reference. /// This is a simplified interface to Py_CompileStringExFlags() below, with optimize set to -1. /// internal static IntPtr Py_CompileStringFlags(string str, string file, int start, IntPtr flags) { return Py_CompileStringExFlags(str, file, start, flags, -1); } /// /// Return value: New reference. /// Like Py_CompileStringObject(), but filename is a byte string decoded from the filesystem encoding(os.fsdecode()). /// /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr Py_CompileStringExFlags(string str, string file, int start, IntPtr flags, int optimize); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_ExecCodeModule(string name, IntPtr code); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyCFunction_NewEx(IntPtr ml, IntPtr self, IntPtr mod); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyMethod_New(IntPtr func, IntPtr self, IntPtr cls); //==================================================================== // Python abstract object API //==================================================================== /// /// Return value: Borrowed reference. /// A macro-like method to get the type of a Python object. This is /// designed to be lean and mean in IL & avoid managed <-> unmanaged /// transitions. Note that this does not incref the type object. /// internal static unsafe IntPtr PyObject_TYPE(IntPtr op) { var p = (void*)op; if ((void*)0 == p) { 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))); } internal static unsafe BorrowedReference PyObject_TYPE(BorrowedReference op) => new BorrowedReference(PyObject_TYPE(op.DangerousGetAddress())); /// /// Managed version of the standard Python C API PyObject_Type call. /// This version avoids a managed <-> unmanaged transition. /// This one does incref the returned type object. /// internal static IntPtr PyObject_Type(IntPtr op) { IntPtr tp = PyObject_TYPE(op); XIncref(tp); return tp; } internal static string PyObject_GetTypeName(IntPtr op) { IntPtr pyType = Marshal.ReadIntPtr(op, ObjectOffset.ob_type); IntPtr ppName = Marshal.ReadIntPtr(pyType, TypeOffset.tp_name); return Marshal.PtrToStringAnsi(ppName); } /// /// Test whether the Python object is an iterable. /// internal static bool PyObject_IsIterable(IntPtr pointer) { var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); IntPtr tp_iter = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iter); return tp_iter != IntPtr.Zero; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_HasAttrString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_GetAttrString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_SetAttrString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_HasAttr(IntPtr pointer, IntPtr name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_GetItem(IntPtr pointer, IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_DelItem(IntPtr pointer, IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_GetIter(IntPtr op); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid); internal static int PyObject_Compare(IntPtr value1, IntPtr value2) { int res; res = PyObject_RichCompareBool(value1, value2, Py_LT); if (-1 == res) return -1; else if (1 == res) return -1; res = PyObject_RichCompareBool(value1, value2, Py_EQ); if (-1 == res) return -1; else if (1 == res) return 0; res = PyObject_RichCompareBool(value1, value2, Py_GT); if (-1 == res) return -1; else if (1 == res) return 1; Exceptions.SetError(Exceptions.SystemError, "Error comparing objects"); return -1; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_IsInstance(IntPtr ob, IntPtr type); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_IsSubclass(IntPtr ob, IntPtr type); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyCallable_Check(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_IsTrue(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_Not(IntPtr pointer); internal static long PyObject_Size(IntPtr pointer) { return (long)_PyObject_Size(pointer); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Size")] private static extern IntPtr _PyObject_Size(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Hash(IntPtr op); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Repr(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Str(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Str")] internal static extern IntPtr PyObject_Unicode(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Dir(IntPtr pointer); #if PYTHON_WITH_PYDEBUG [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void _Py_NewReference(IntPtr ob); #endif //==================================================================== // Python buffer API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_GetBuffer(IntPtr exporter, ref Py_buffer view, int flags); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyBuffer_Release(ref Py_buffer view); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] internal static extern IntPtr PyBuffer_SizeFromFormat([MarshalAs(UnmanagedType.LPStr)] string format); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyBuffer_IsContiguous(ref Py_buffer view, char order); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyBuffer_GetPointer(ref Py_buffer view, IntPtr[] indices); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyBuffer_FromContiguous(ref Py_buffer view, IntPtr buf, IntPtr len, char fort); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyBuffer_ToContiguous(IntPtr buf, ref Py_buffer src, IntPtr len, char order); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyBuffer_FillContiguousStrides(int ndims, IntPtr shape, IntPtr strides, int itemsize, char order); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyBuffer_FillInfo(ref Py_buffer view, IntPtr exporter, IntPtr buf, IntPtr len, int _readonly, int flags); //==================================================================== // Python number API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyNumber_Long")] internal static extern IntPtr PyNumber_Int(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Long(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Float(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern bool PyNumber_Check(IntPtr ob); internal static bool PyInt_Check(BorrowedReference ob) => PyObject_TypeCheck(ob, new BorrowedReference(PyIntType)); internal static bool PyInt_Check(IntPtr ob) { return PyObject_TypeCheck(ob, PyIntType); } internal static bool PyBool_Check(IntPtr ob) { return PyObject_TypeCheck(ob, PyBoolType); } internal static IntPtr PyInt_FromInt32(int value) { var v = new IntPtr(value); return PyInt_FromLong(v); } internal static IntPtr PyInt_FromInt64(long value) { var v = new IntPtr(value); return PyInt_FromLong(v); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_FromLong")] private static extern IntPtr PyInt_FromLong(IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_AsLong")] internal static extern int PyInt_AsLong(IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_FromString")] internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); internal static bool PyLong_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyLongType; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromLong(long value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_FromUnsignedLong")] internal static extern IntPtr PyLong_FromUnsignedLong32(uint value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_FromUnsignedLong")] internal static extern IntPtr PyLong_FromUnsignedLong64(ulong value); internal static IntPtr PyLong_FromUnsignedLong(object value) { if (Is32Bit || IsWindows) return PyLong_FromUnsignedLong32(Convert.ToUInt32(value)); else return PyLong_FromUnsignedLong64(Convert.ToUInt64(value)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromDouble(double value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromLongLong(long value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromUnsignedLongLong(ulong value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromString(string value, IntPtr end, int radix); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyLong_AsLong(IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_AsUnsignedLong")] internal static extern uint PyLong_AsUnsignedLong32(IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_AsUnsignedLong")] internal static extern ulong PyLong_AsUnsignedLong64(IntPtr value); internal static object PyLong_AsUnsignedLong(IntPtr value) { if (Is32Bit || IsWindows) return PyLong_AsUnsignedLong32(value); else return PyLong_AsUnsignedLong64(value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern long PyLong_AsLongLong(BorrowedReference value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern long PyLong_AsLongLong(IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern ulong PyLong_AsUnsignedLongLong(IntPtr value); internal static bool PyFloat_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyFloatType; } /// /// Return value: New reference. /// Create a Python integer from the pointer p. The pointer value can be retrieved from the resulting value using PyLong_AsVoidPtr(). /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_FromVoidPtr(IntPtr p); /// /// Convert a Python integer pylong to a C void pointer. If pylong cannot be converted, an OverflowError will be raised. This is only assured to produce a usable void pointer for values created with PyLong_FromVoidPtr(). /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyLong_AsVoidPtr(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyFloat_FromDouble(double value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyFloat_FromString(IntPtr value, IntPtr junk); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern double PyFloat_AsDouble(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Add(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Subtract(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Multiply(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_TrueDivide(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_And(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Xor(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Or(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Lshift(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Rshift(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Power(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Remainder(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceAdd(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceSubtract(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceMultiply(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceTrueDivide(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceAnd(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceXor(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceOr(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceLshift(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceRshift(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlacePower(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_InPlaceRemainder(IntPtr o1, IntPtr o2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Negative(IntPtr o1); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Positive(IntPtr o1); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Invert(IntPtr o1); //==================================================================== // Python sequence API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern bool PySequence_Check(IntPtr pointer); internal static IntPtr PySequence_GetItem(IntPtr pointer, long index) { return PySequence_GetItem(pointer, new IntPtr(index)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PySequence_GetItem(IntPtr pointer, IntPtr index); internal static int PySequence_SetItem(IntPtr pointer, long index, IntPtr value) { return PySequence_SetItem(pointer, new IntPtr(index), value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PySequence_SetItem(IntPtr pointer, IntPtr index, IntPtr value); internal static int PySequence_DelItem(IntPtr pointer, long index) { return PySequence_DelItem(pointer, new IntPtr(index)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PySequence_DelItem(IntPtr pointer, IntPtr index); internal static IntPtr PySequence_GetSlice(IntPtr pointer, long i1, long i2) { return PySequence_GetSlice(pointer, new IntPtr(i1), new IntPtr(i2)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PySequence_GetSlice(IntPtr pointer, IntPtr i1, IntPtr i2); internal static int PySequence_SetSlice(IntPtr pointer, long i1, long i2, IntPtr v) { return PySequence_SetSlice(pointer, new IntPtr(i1), new IntPtr(i2), v); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PySequence_SetSlice(IntPtr pointer, IntPtr i1, IntPtr i2, IntPtr v); internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2) { return PySequence_DelSlice(pointer, new IntPtr(i1), new IntPtr(i2)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PySequence_DelSlice(IntPtr pointer, IntPtr i1, IntPtr i2); internal static long PySequence_Size(IntPtr pointer) { return (long)_PySequence_Size(pointer); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")] private static extern IntPtr _PySequence_Size(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PySequence_Contains(IntPtr pointer, IntPtr item); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PySequence_Concat(IntPtr pointer, IntPtr other); internal static IntPtr PySequence_Repeat(IntPtr pointer, long count) { return PySequence_Repeat(pointer, new IntPtr(count)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PySequence_Repeat(IntPtr pointer, IntPtr count); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PySequence_Index(IntPtr pointer, IntPtr item); internal static long PySequence_Count(IntPtr pointer, IntPtr value) { return (long)_PySequence_Count(pointer, value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Count")] private static extern IntPtr _PySequence_Count(IntPtr pointer, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PySequence_Tuple(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PySequence_List(IntPtr pointer); //==================================================================== // Python string API //==================================================================== internal static bool IsStringType(IntPtr op) { IntPtr t = PyObject_TYPE(op); return (t == PyStringType) || (t == PyUnicodeType); } internal static bool PyString_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyStringType; } internal static IntPtr PyString_FromString(string value) { return PyUnicode_FromKindAndData(_UCS, value, value.Length); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyBytes_FromString(string op); internal static long PyBytes_Size(IntPtr op) { return (long)_PyBytes_Size(op); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")] private static extern IntPtr _PyBytes_Size(IntPtr op); internal static IntPtr PyBytes_AS_STRING(IntPtr ob) { return ob + BytesOffset.ob_sval; } internal static IntPtr PyUnicode_FromStringAndSize(IntPtr value, long size) { return PyUnicode_FromStringAndSize(value, new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyUnicode_FromStringAndSize(IntPtr value, IntPtr size); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_AsUTF8(IntPtr unicode); internal static bool PyUnicode_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyUnicodeType; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_FromObject(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); internal static IntPtr PyUnicode_FromKindAndData(int kind, string s, long size) { return PyUnicode_FromKindAndData(kind, s, new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyUnicode_FromKindAndData( int kind, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, IntPtr size ); internal static IntPtr PyUnicode_FromUnicode(string s, long size) { return PyUnicode_FromKindAndData(_UCS, s, size); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyUnicode_GetMax(); internal static long PyUnicode_GetSize(IntPtr ob) { return (long)_PyUnicode_GetSize(ob); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyUnicode_GetSize")] private static extern IntPtr _PyUnicode_GetSize(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_AsUnicode(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_FromOrdinal(int c); internal static IntPtr PyUnicode_FromString(string s) { return PyUnicode_FromUnicode(s, s.Length); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyUnicode_InternFromString(string s); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyUnicode_Compare(IntPtr left, IntPtr right); internal static string GetManagedString(in BorrowedReference borrowedReference) => GetManagedString(borrowedReference.DangerousGetAddress()); /// /// Function to access the internal PyUnicode/PyString object and /// convert it to a managed string with the correct encoding. /// /// /// We can't easily do this through through the CustomMarshaler's on /// the returns because will have access to the IntPtr but not size. /// /// For PyUnicodeType, we can't convert with Marshal.PtrToStringUni /// since it only works for UCS2. /// /// PyStringType or PyUnicodeType object to convert /// Managed String internal static string GetManagedString(IntPtr op) { IntPtr type = PyObject_TYPE(op); if (type == PyUnicodeType) { IntPtr p = PyUnicode_AsUnicode(op); int length = (int)PyUnicode_GetSize(op); int size = length * _UCS; var buffer = new byte[size]; Marshal.Copy(p, buffer, 0, size); return PyEncoding.GetString(buffer, 0, size); } return null; } //==================================================================== // Python dictionary API //==================================================================== internal static bool PyDict_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyDictType; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_New(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_Next(IntPtr p, out IntPtr ppos, out IntPtr pkey, out IntPtr pvalue); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDictProxy_New(IntPtr dict); /// /// Return value: Borrowed reference. /// Return NULL if the key key is not present, but without setting an exception. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern BorrowedReference PyDict_GetItemWithError(BorrowedReference pointer, BorrowedReference key); /// /// Return value: Borrowed reference. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_GetItemString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string key); /// /// Return 0 on success or -1 on failure. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value); /// /// Return 0 on success or -1 on failure. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_SetItemString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string key, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_DelItem(IntPtr pointer, IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_DelItemString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyMapping_HasKey(IntPtr pointer, IntPtr key); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_Keys(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_Values(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern NewReference PyDict_Items(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyDict_Copy(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyDict_Update(IntPtr pointer, IntPtr other); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyDict_Clear(IntPtr pointer); internal static long PyDict_Size(IntPtr pointer) { return (long)_PyDict_Size(pointer); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyDict_Size")] internal static extern IntPtr _PyDict_Size(IntPtr pointer); /// /// Return value: New reference. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PySet_New(IntPtr iterable); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PySet_Add(IntPtr set, IntPtr key); /// /// Return 1 if found, 0 if not found, and -1 if an error is encountered. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PySet_Contains(IntPtr anyset, IntPtr key); //==================================================================== // Python list API //==================================================================== internal static bool PyList_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyListType; } internal static IntPtr PyList_New(long size) { return PyList_New(new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyList_New(IntPtr size); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyList_AsTuple(IntPtr pointer); internal static BorrowedReference PyList_GetItem(BorrowedReference pointer, long index) { return PyList_GetItem(pointer, new IntPtr(index)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern BorrowedReference PyList_GetItem(BorrowedReference pointer, IntPtr index); internal static int PyList_SetItem(IntPtr pointer, long index, IntPtr value) { return PyList_SetItem(pointer, new IntPtr(index), value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PyList_SetItem(IntPtr pointer, IntPtr index, IntPtr value); internal static int PyList_Insert(BorrowedReference pointer, long index, IntPtr value) { return PyList_Insert(pointer, new IntPtr(index), value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PyList_Insert(BorrowedReference pointer, IntPtr index, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyList_Append(BorrowedReference pointer, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyList_Reverse(BorrowedReference pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyList_Sort(BorrowedReference pointer); internal static IntPtr PyList_GetSlice(IntPtr pointer, long start, long end) { return PyList_GetSlice(pointer, new IntPtr(start), new IntPtr(end)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyList_GetSlice(IntPtr pointer, IntPtr start, IntPtr end); internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr value) { return PyList_SetSlice(pointer, new IntPtr(start), new IntPtr(end), value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PyList_SetSlice(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value); internal static long PyList_Size(BorrowedReference pointer) { return (long)_PyList_Size(pointer); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")] private static extern IntPtr _PyList_Size(BorrowedReference pointer); //==================================================================== // Python tuple API //==================================================================== internal static bool PyTuple_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyTupleType; } internal static IntPtr PyTuple_New(long size) { return PyTuple_New(new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyTuple_New(IntPtr size); internal static BorrowedReference PyTuple_GetItem(BorrowedReference pointer, long index) => PyTuple_GetItem(pointer, new IntPtr(index)); internal static IntPtr PyTuple_GetItem(IntPtr pointer, long index) { return PyTuple_GetItem(pointer, new IntPtr(index)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern BorrowedReference PyTuple_GetItem(BorrowedReference pointer, IntPtr index); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyTuple_GetItem(IntPtr pointer, IntPtr index); internal static int PyTuple_SetItem(IntPtr pointer, long index, IntPtr value) { return PyTuple_SetItem(pointer, new IntPtr(index), value); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern int PyTuple_SetItem(IntPtr pointer, IntPtr index, IntPtr value); internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end) { return PyTuple_GetSlice(pointer, new IntPtr(start), new IntPtr(end)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyTuple_GetSlice(IntPtr pointer, IntPtr start, IntPtr end); internal static long PyTuple_Size(IntPtr pointer) { return (long)_PyTuple_Size(pointer); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyTuple_Size")] private static extern IntPtr _PyTuple_Size(IntPtr pointer); //==================================================================== // Python iterator API //==================================================================== internal static bool PyIter_Check(IntPtr pointer) { var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); IntPtr tp_iternext = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iternext); return tp_iternext != IntPtr.Zero && tp_iternext != _PyObject_NextNotImplemented; } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyIter_Next(IntPtr pointer); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern NewReference PyIter_Next(BorrowedReference pointer); //==================================================================== // Python module API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyModule_New(string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern string PyModule_GetName(IntPtr module); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyModule_GetDict(IntPtr module); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern string PyModule_GetFilename(IntPtr module); #if PYTHON_WITH_PYDEBUG [DllImport(_PythonDll, EntryPoint = "PyModule_Create2TraceRefs", CallingConvention = CallingConvention.Cdecl)] #else [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] #endif internal static extern IntPtr PyModule_Create2(IntPtr module, int apiver); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_Import(IntPtr name); /// /// Return value: New reference. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_ImportModule(string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_ReloadModule(IntPtr module); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_AddModule(string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyImport_GetModuleDict(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PySys_SetArgvEx( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, int updatepath ); /// /// Return value: Borrowed reference. /// Return the object name from the sys module or NULL if it does not exist, without setting an exception. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern BorrowedReference PySys_GetObject(string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PySys_SetObject(string name, IntPtr ob); //==================================================================== // Python type object API //==================================================================== internal static bool PyType_Check(IntPtr ob) { return PyObject_TypeCheck(ob, PyTypeType); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyType_Modified(IntPtr type); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern bool PyType_IsSubtype(IntPtr t1, IntPtr t2); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern bool PyType_IsSubtype(BorrowedReference t1, BorrowedReference t2); internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) => PyObject_TypeCheck(new BorrowedReference(ob), new BorrowedReference(tp)); internal static bool PyObject_TypeCheck(BorrowedReference ob, BorrowedReference tp) { BorrowedReference t = PyObject_TYPE(ob); return (t == tp) || PyType_IsSubtype(t, tp); } internal static bool PyType_IsSameAsOrSubtype(IntPtr type, IntPtr ofType) { return (type == ofType) || PyType_IsSubtype(type, ofType); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kw); internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) { return PyType_GenericAlloc(type, new IntPtr(n)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n); /// /// Finalize a type object. This should be called on all type objects to finish their initialization. This function is responsible for adding inherited slots from a type’s base class. Return 0 on success, or return -1 and sets an exception on error. /// [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyType_Ready(IntPtr type); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr _PyType_Lookup(IntPtr type, IntPtr name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_GenericGetAttr(IntPtr obj, IntPtr name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr _PyObject_GetDictPtr(IntPtr obj); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyObject_GC_Del(IntPtr tp); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyObject_GC_Track(IntPtr tp); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyObject_GC_UnTrack(IntPtr tp); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void _PyObject_Dump(IntPtr ob); //==================================================================== // Python memory API //==================================================================== internal static IntPtr PyMem_Malloc(long size) { return PyMem_Malloc(new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyMem_Malloc(IntPtr size); internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) { return PyMem_Realloc(ptr, new IntPtr(size)); } [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyMem_Realloc(IntPtr ptr, IntPtr size); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyMem_Free(IntPtr ptr); //==================================================================== // Python exception API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_SetString(IntPtr ob, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string message); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_SetObject(BorrowedReference type, BorrowedReference exceptionObject); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyErr_SetFromErrno(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_SetNone(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyErr_ExceptionMatches(IntPtr exception); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_NormalizeException(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyErr_Occurred(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_Clear(); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyErr_Print(); //==================================================================== // Cell API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern NewReference PyCell_Get(BorrowedReference cell); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyCell_Set(BorrowedReference cell, IntPtr value); //==================================================================== // Python GC API //==================================================================== internal const int _PyGC_REFS_SHIFT = 1; internal const long _PyGC_REFS_UNTRACKED = -2; internal const long _PyGC_REFS_REACHABLE = -3; internal const long _PyGC_REFS_TENTATIVELY_UNREACHABLE = -4; [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyGC_Collect(); internal static IntPtr _Py_AS_GC(IntPtr ob) { // XXX: PyGC_Head has a force alignment depend on platform. // See PyGC_Head in objimpl.h for more details. return Is32Bit ? ob - 16 : ob - 24; } internal static IntPtr _Py_FROM_GC(IntPtr gc) { return Is32Bit ? gc + 16 : gc + 24; } internal static IntPtr _PyGCHead_REFS(IntPtr gc) { unsafe { var pGC = (PyGC_Head*)gc; var refs = pGC->gc.gc_refs; if (Is32Bit) { return new IntPtr(refs.ToInt32() >> _PyGC_REFS_SHIFT); } return new IntPtr(refs.ToInt64() >> _PyGC_REFS_SHIFT); } } internal static IntPtr _PyGC_REFS(IntPtr ob) { return _PyGCHead_REFS(_Py_AS_GC(ob)); } internal static bool _PyObject_GC_IS_TRACKED(IntPtr ob) { return (long)_PyGC_REFS(ob) != _PyGC_REFS_UNTRACKED; } internal static void Py_CLEAR(ref IntPtr ob) { XDecref(ob); ob = IntPtr.Zero; } //==================================================================== // Python Capsules API //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern NewReference PyCapsule_New(IntPtr pointer, string name, IntPtr destructor); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyCapsule_GetPointer(BorrowedReference capsule, string name); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int PyCapsule_SetPointer(BorrowedReference capsule, IntPtr pointer); //==================================================================== // Miscellaneous //==================================================================== [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyMethod_Self(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyMethod_Function(IntPtr ob); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_AddPendingCall(IntPtr func, IntPtr arg); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern int Py_MakePendingCalls(); internal static void SetNoSiteFlag() { var loader = LibraryLoader.Instance; IntPtr dllLocal = IntPtr.Zero; if (_PythonDll != "__Internal") { dllLocal = loader.Load(_PythonDll); if (dllLocal == IntPtr.Zero) { throw new Exception($"Cannot load {_PythonDll}"); } } try { Py_NoSiteFlag = loader.GetFunction(dllLocal, "Py_NoSiteFlag"); Marshal.WriteInt32(Py_NoSiteFlag, 1); } finally { if (dllLocal != IntPtr.Zero) { loader.Free(dllLocal); } } } /// /// Return value: New reference. /// internal static IntPtr GetBuiltins() { return PyImport_Import(PyIdentifier.builtins); } } public enum ShutdownMode { Default, Normal, Soft, Reload, } class PyReferenceCollection { private List> _actions = new List>(); /// /// Record obj's address to release the obj in the future, /// obj must alive before calling Release. /// public void Add(IntPtr ob, Action onRelease) { _actions.Add(new KeyValuePair(ob, onRelease)); } public void Release() { foreach (var item in _actions) { Runtime.XDecref(item.Key); item.Value?.Invoke(); } _actions.Clear(); } } }
X Tutup