diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 688d65c04..3c8fabcc1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,9 +12,33 @@ jobs: fail-fast: false matrix: os: [windows, ubuntu, macos] - python: [3.6, 3.7, 3.8, 3.9] + pyver_minor: [6, 7, 8, 9] platform: [x64] shutdown_mode: [Normal, Soft] + include: + - os: ubuntu + pyver_minor: 6 + dll_suffix: m + - os: ubuntu + pyver_minor: 7 + dll_suffix: m + + - os: macos + dll_prefix: lib + dll_pyver_major: '3.' + dll_suffix: m + - os: ubuntu + dll_prefix: lib + dll_pyver_major: '3.' + - os: windows + dll_pyver_major: '3' + + - os: ubuntu + dll_ext: .so + - os: windows + dll_ext: .dll + - os: macos + dll_ext: .dylib env: PYTHONNET_SHUTDOWN_MODE: ${{ matrix.SHUTDOWN_MODE }} @@ -32,10 +56,10 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 - - name: Set up Python ${{ matrix.python }} + - name: Set up Python 3.${{ matrix.pyver_minor }} uses: actions/setup-python@v2 with: - python-version: ${{ matrix.python }} + python-version: 3.${{ matrix.pyver_minor }} architecture: ${{ matrix.platform }} - name: Install dependencies @@ -47,16 +71,28 @@ jobs: python setup.py configure pip install -v . + # TODO this should be gone once clr module sets PythonDLL or preloads it + - name: Python Tests + run: pytest + if: ${{ matrix.os != 'macos' }} + env: + PYTHONNET_PYDLL: ${{ matrix.DLL_PREFIX }}python${{matrix.DLL_PYVER_MAJOR}}${{matrix.PYVER_MINOR}}${{matrix.DLL_SUFFIX}}${{matrix.DLL_EXT}} + - name: Python Tests run: pytest + if: ${{ matrix.os == 'macos' }} - name: Embedding tests run: dotnet test --runtime any-${{ matrix.platform }} src/embed_tests/ if: ${{ matrix.os != 'macos' }} # Not working right now, doesn't find libpython + env: + PYTHONNET_PYDLL: ${{ matrix.DLL_PREFIX }}python${{matrix.DLL_PYVER_MAJOR}}${{matrix.PYVER_MINOR}}${{matrix.DLL_SUFFIX}}${{matrix.DLL_EXT}} - name: Python tests run from .NET run: dotnet test --runtime any-${{ matrix.platform }} src/python_tests_runner/ if: ${{ matrix.os == 'windows' }} # Not working for others right now + env: + PYTHONNET_PYDLL: ${{ matrix.DLL_PREFIX }}python${{matrix.DLL_PYVER_MAJOR}}${{matrix.PYVER_MINOR}}${{matrix.DLL_SUFFIX}}${{matrix.DLL_EXT}} # TODO: Run perf tests # TODO: Run mono tests on Windows? diff --git a/CHANGELOG.md b/CHANGELOG.md index 60d516488..d64f3cdef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ details about the cause of the failure when .NET expects an integer [#1342][i1342] - More specific error messages for method argument mismatch - BREAKING: Methods with `ref` or `out` parameters and void return type return a tuple of only the `ref` and `out` parameters. +- BREAKING: to call Python from .NET `Runtime.PythonDLL` property must be set to Python DLL name +or the DLL must be loaded in advance. This must be done before calling any other Python.NET functions. ### Fixed @@ -57,6 +59,8 @@ when .NET expects an integer [#1342][i1342] ### Removed - implicit assembly loading (you have to explicitly `clr.AddReference` before doing import) +- support for .NET Framework 4.0-4.6; Mono before 5.4. Python.NET now requires .NET Standard 2.0 +(see [the matrix](https://docs.microsoft.com/en-us/dotnet/standard/net-standard#net-implementation-support)) ## [2.5.0][] - 2020-06-14 diff --git a/Directory.Build.props b/Directory.Build.props index 5ad0c0e77..cad319287 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,7 +8,11 @@ - + + all + runtime; build; native; contentfiles; analyzers + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/appveyor.yml b/appveyor.yml index 1ad673ede..21e816f38 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,6 +30,7 @@ environment: init: # Update Environment Variables based on matrix/platform - set PY_VER=%PYTHON_VERSION:.=% + - set PYTHONNET_PYDLL=python%PY_VER%.dll - set PYTHON=C:\PYTHON%PY_VER% - if %PLATFORM%==x64 (set PYTHON=%PYTHON%-x64) diff --git a/src/console/pythonconsole.cs b/src/console/pythonconsole.cs index 912e9bb0d..bf17848f7 100644 --- a/src/console/pythonconsole.cs +++ b/src/console/pythonconsole.cs @@ -26,7 +26,7 @@ private PythonConsole() [STAThread] public static int Main(string[] args) { - // Only net40 is capable to safely inject python.runtime.dll into resources. + // Only .NET Framework is capable to safely inject python.runtime.dll into resources. #if NET40 // reference the static assemblyLoader to stop it being optimized away AssemblyLoader a = assemblyLoader; diff --git a/src/embed_tests/References.cs b/src/embed_tests/References.cs index 1d29e85c7..417e743c0 100644 --- a/src/embed_tests/References.cs +++ b/src/embed_tests/References.cs @@ -23,7 +23,7 @@ public void Dispose() public void MoveToPyObject_SetsNull() { var dict = new PyDict(); - NewReference reference = Runtime.PyDict_Items(dict.Handle); + NewReference reference = Runtime.PyDict_Items(dict.Reference); try { Assert.IsFalse(reference.IsNull()); @@ -41,7 +41,7 @@ public void MoveToPyObject_SetsNull() public void CanBorrowFromNewReference() { var dict = new PyDict(); - NewReference reference = Runtime.PyDict_Items(dict.Handle); + NewReference reference = Runtime.PyDict_Items(dict.Reference); try { PythonException.ThrowIfIsNotZero(Runtime.PyList_Reverse(reference)); diff --git a/src/embed_tests/TestDomainReload.cs b/src/embed_tests/TestDomainReload.cs index f8445edb4..e4479da18 100644 --- a/src/embed_tests/TestDomainReload.cs +++ b/src/embed_tests/TestDomainReload.cs @@ -332,7 +332,7 @@ static void RunAssemblyAndUnload(string domainName) // assembly (and Python .NET) to reside var theProxy = CreateInstanceInstanceAndUnwrap(domain); - theProxy.Call("InitPython", ShutdownMode.Soft); + theProxy.Call(nameof(PythonRunner.InitPython), ShutdownMode.Soft, PyRuntime.PythonDLL); // From now on use the Proxy to call into the new assembly theProxy.RunPython(); @@ -400,7 +400,7 @@ static void RunDomainReloadSteps() where T1 : CrossCaller where T2 : Cro try { var theProxy = CreateInstanceInstanceAndUnwrap(domain); - theProxy.Call("InitPython", ShutdownMode.Reload); + theProxy.Call(nameof(PythonRunner.InitPython), ShutdownMode.Reload, PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap(domain); arg = caller.Execute(arg); @@ -418,7 +418,7 @@ static void RunDomainReloadSteps() where T1 : CrossCaller where T2 : Cro try { var theProxy = CreateInstanceInstanceAndUnwrap(domain); - theProxy.Call("InitPython", ShutdownMode.Reload); + theProxy.Call(nameof(PythonRunner.InitPython), ShutdownMode.Reload, PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap(domain); caller.Execute(arg); @@ -478,8 +478,9 @@ public static void RunPython() private static IntPtr _state; - public static void InitPython(ShutdownMode mode) + public static void InitPython(ShutdownMode mode, string dllName) { + PyRuntime.PythonDLL = dllName; PythonEngine.Initialize(mode: mode); _state = PythonEngine.BeginAllowThreads(); } diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs index cde5dd6fa..59c66cc5e 100644 --- a/src/embed_tests/TestRuntime.cs +++ b/src/embed_tests/TestRuntime.cs @@ -96,13 +96,15 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test() // TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check. var threading = Runtime.Runtime.PyImport_ImportModule("threading"); Exceptions.ErrorCheck(threading); - var threadingDict = Runtime.Runtime.PyModule_GetDict(threading); + var threadingDict = Runtime.Runtime.PyModule_GetDict(new BorrowedReference(threading)); Exceptions.ErrorCheck(threadingDict); var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock"); - if (lockType == IntPtr.Zero) + if (lockType.IsNull) throw new KeyNotFoundException("class 'Lock' was not found in 'threading'"); - var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0)); + var args = Runtime.Runtime.PyTuple_New(0); + var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType.DangerousGetAddress(), args); + Runtime.Runtime.XDecref(args); Exceptions.ErrorCheck(lockInstance); Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance)); diff --git a/src/embed_tests/TestTypeManager.cs b/src/embed_tests/TestTypeManager.cs deleted file mode 100644 index 43155e1bf..000000000 --- a/src/embed_tests/TestTypeManager.cs +++ /dev/null @@ -1,65 +0,0 @@ -using NUnit.Framework; -using Python.Runtime; -using Python.Runtime.Platform; -using System.Runtime.InteropServices; - -namespace Python.EmbeddingTest -{ - class TestTypeManager - { - [SetUp] - public static void Init() - { - Runtime.Runtime.Initialize(); - } - - [TearDown] - public static void Fini() - { - Runtime.Runtime.Shutdown(); - } - - [Test] - public static void TestNativeCode() - { - Assert.That(() => { var _ = NativeCodePageHelper.NativeCode.Active; }, Throws.Nothing); - Assert.That(NativeCodePageHelper.NativeCode.Active.Code.Length, Is.GreaterThan(0)); - } - - [Test] - public static void TestMemoryMapping() - { - Assert.That(() => { var _ = NativeCodePageHelper.CreateMemoryMapper(); }, Throws.Nothing); - var mapper = NativeCodePageHelper.CreateMemoryMapper(); - - // Allocate a read-write page. - int len = 12; - var page = mapper.MapWriteable(len); - Assert.That(() => { Marshal.WriteInt64(page, 17); }, Throws.Nothing); - Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17)); - - // Mark it read-execute. We can still read, haven't changed any values. - mapper.SetReadExec(page, len); - Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17)); - - // Test that we can't write to the protected page. - // - // We can't actually test access protection under Microsoft - // versions of .NET, because AccessViolationException is assumed to - // mean we're in a corrupted state: - // https://stackoverflow.com/questions/3469368/how-to-handle-accessviolationexception - // - // We can test under Mono but it throws NRE instead of AccessViolationException. - // - // We can't use compiler flags because we compile with MONO_LINUX - // while running on the Microsoft .NET Core during continuous - // integration tests. - /* if (System.Type.GetType ("Mono.Runtime") != null) - { - // Mono throws NRE instead of AccessViolationException for some reason. - Assert.That(() => { Marshal.WriteInt64(page, 73); }, Throws.TypeOf()); - Assert.That(Marshal.ReadInt64(page), Is.EqualTo(17)); - } */ - } - } -} diff --git a/src/runtime/BorrowedReference.cs b/src/runtime/BorrowedReference.cs index a9ea327e9..2f5c347c7 100644 --- a/src/runtime/BorrowedReference.cs +++ b/src/runtime/BorrowedReference.cs @@ -10,10 +10,11 @@ readonly ref struct BorrowedReference readonly IntPtr pointer; public bool IsNull => this.pointer == IntPtr.Zero; - /// Gets a raw pointer to the Python object public IntPtr DangerousGetAddress() => this.IsNull ? throw new NullReferenceException() : this.pointer; + /// Gets a raw pointer to the Python object + public IntPtr DangerousGetAddressOrNull() => this.pointer; /// /// Creates new instance of from raw pointer. Unsafe. diff --git a/src/runtime/CustomMarshaler.cs b/src/runtime/CustomMarshaler.cs index 0cbbbaba2..4814e6c0b 100644 --- a/src/runtime/CustomMarshaler.cs +++ b/src/runtime/CustomMarshaler.cs @@ -41,8 +41,9 @@ public int GetNativeDataSize() /// internal class UcsMarshaler : MarshalerBase { + internal static readonly int _UCS = Runtime.PyUnicode_GetMax() <= 0xFFFF ? 2 : 4; + internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32; private static readonly MarshalerBase Instance = new UcsMarshaler(); - private static readonly Encoding PyEncoding = Runtime.PyEncoding; public override IntPtr MarshalManagedToNative(object managedObj) { @@ -91,13 +92,13 @@ public static int GetUnicodeByteLength(IntPtr p) var len = 0; while (true) { - int c = Runtime._UCS == 2 + int c = _UCS == 2 ? Marshal.ReadInt16(p, len * 2) : Marshal.ReadInt32(p, len * 4); if (c == 0) { - return len * Runtime._UCS; + return len * _UCS; } checked { @@ -147,7 +148,7 @@ public static string PtrToPy3UnicodePy2String(IntPtr p) internal class StrArrayMarshaler : MarshalerBase { private static readonly MarshalerBase Instance = new StrArrayMarshaler(); - private static readonly Encoding PyEncoding = Runtime.PyEncoding; + private static readonly Encoding PyEncoding = UcsMarshaler.PyEncoding; public override IntPtr MarshalManagedToNative(object managedObj) { @@ -159,7 +160,7 @@ public override IntPtr MarshalManagedToNative(object managedObj) } int totalStrLength = argv.Sum(arg => arg.Length + 1); - int memSize = argv.Length * IntPtr.Size + totalStrLength * Runtime._UCS; + int memSize = argv.Length * IntPtr.Size + totalStrLength * UcsMarshaler._UCS; IntPtr mem = Marshal.AllocHGlobal(memSize); try diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs index a4ed75918..f19dfd04c 100644 --- a/src/runtime/NewReference.cs +++ b/src/runtime/NewReference.cs @@ -11,6 +11,16 @@ ref struct NewReference { IntPtr pointer; + /// Creates a pointing to the same object + public NewReference(BorrowedReference reference, bool canBeNull = false) + { + var address = canBeNull + ? reference.DangerousGetAddressOrNull() + : reference.DangerousGetAddress(); + Runtime.XIncref(address); + this.pointer = address; + } + [Pure] public static implicit operator BorrowedReference(in NewReference reference) => new BorrowedReference(reference.pointer); @@ -28,6 +38,16 @@ public PyObject MoveToPyObject() 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() { diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 4939fae34..32a467dd8 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -2,9 +2,9 @@ netstandard2.0 AnyCPU + 9.0 Python.Runtime Python.Runtime - 9.0 pythonnet https://github.com/pythonnet/pythonnet/blob/master/LICENSE https://github.com/pythonnet/pythonnet diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index 0cbff371f..1ee06e682 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -117,7 +117,7 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage) // Python object's dictionary tool; thus raising an AttributeError // instead of a TypeError. // Classes are re-initialized on in RestoreRuntimeData. - IntPtr dict = Marshal.ReadIntPtr(cls.Value.tpHandle, TypeOffset.tp_dict); + var dict = new BorrowedReference(Marshal.ReadIntPtr(cls.Value.tpHandle, TypeOffset.tp_dict)); foreach (var member in cls.Value.dotNetMembers) { // No need to decref the member, the ClassBase instance does @@ -269,7 +269,7 @@ private static void InitClassBase(Type type, ClassBase impl) IntPtr tp = TypeManager.GetTypeHandle(impl, type); // Finally, initialize the class __dict__ and return the object. - IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict); + var dict = new BorrowedReference(Marshal.ReadIntPtr(tp, TypeOffset.tp_dict)); if (impl.dotNetMembers == null) @@ -282,7 +282,7 @@ private static void InitClassBase(Type type, ClassBase impl) var item = (ManagedType)iter.Value; var name = (string)iter.Key; impl.dotNetMembers.Add(name); - Runtime.PyDict_SetItemString(dict, name, item.pyHandle); + Runtime.PyDict_SetItemString(dict, name, item.ObjectReference); // Decref the item now that it's been used. item.DecrRefCount(); if (ClassBase.CilToPyOpMap.TryGetValue(name, out var pyOp)) { @@ -291,20 +291,15 @@ private static void InitClassBase(Type type, ClassBase impl) } // If class has constructors, generate an __doc__ attribute. - IntPtr doc = IntPtr.Zero; + NewReference doc = default; Type marker = typeof(DocStringAttribute); var attrs = (Attribute[])type.GetCustomAttributes(marker, false); - if (attrs.Length == 0) - { - doc = IntPtr.Zero; - } - else + if (attrs.Length != 0) { var attr = (DocStringAttribute)attrs[0]; string docStr = attr.DocString; - doc = Runtime.PyString_FromString(docStr); + doc = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docStr)); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); - Runtime.XDecref(doc); } var co = impl as ClassObject; @@ -320,20 +315,21 @@ private static void InitClassBase(Type type, ClassBase impl) var ctors = new ConstructorBinding(type, tp, co.binder); // ExtensionType types are untracked, so don't Incref() them. // TODO: deprecate __overloads__ soon... - Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.pyHandle); - Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.pyHandle); + Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.ObjectReference); + Runtime.PyDict_SetItem(dict, PyIdentifier.Overloads, ctors.ObjectReference); ctors.DecrRefCount(); } // don't generate the docstring if one was already set from a DocStringAttribute. - if (!CLRModule._SuppressDocs && doc == IntPtr.Zero) + if (!CLRModule._SuppressDocs && doc.IsNull()) { doc = co.GetDocString(); Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, doc); - Runtime.XDecref(doc); } } } + doc.Dispose(); + // The type has been modified after PyType_Ready has been called // Refresh the type Runtime.PyType_Modified(tp); diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 826ae5c54..4aa97f648 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -31,7 +31,7 @@ internal ClassObject(Type tp) : base(tp) /// /// Helper to get docstring from reflected constructor info. /// - internal IntPtr GetDocString() + internal NewReference GetDocString() { MethodBase[] methods = binder.GetMethods(); var str = ""; @@ -43,7 +43,7 @@ internal IntPtr GetDocString() } str += t.ToString(); } - return Runtime.PyString_FromString(str); + return NewReference.DangerousFromPointer(Runtime.PyString_FromString(str)); } diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 54124ad34..f3b378113 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -241,9 +241,9 @@ internal static IntPtr ToPython(object value, Type type) // return Runtime.PyFloat_FromDouble((double)((float)value)); string ss = ((float)value).ToString(nfi); IntPtr ps = Runtime.PyString_FromString(ss); - IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero); + NewReference op = Runtime.PyFloat_FromString(new BorrowedReference(ps));; Runtime.XDecref(ps); - return op; + return op.DangerousMoveToPointerOrNull(); case TypeCode.Double: return Runtime.PyFloat_FromDouble((double)value); diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 9091fd071..afd0bc14e 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -194,14 +194,16 @@ internal static void SetArgsAndCause(IntPtr ob) /// Shortcut for (pointer == NULL) -> throw PythonException /// /// Pointer to a Python object - internal static void ErrorCheck(IntPtr pointer) + internal static void ErrorCheck(BorrowedReference pointer) { - if (pointer == IntPtr.Zero) + if (pointer.IsNull) { throw new PythonException(); } } + internal static void ErrorCheck(IntPtr pointer) => ErrorCheck(new BorrowedReference(pointer)); + /// /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException /// diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index af6174188..066c765fe 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -13,6 +13,7 @@ internal static class ImportHook private static CLRModule root; private static MethodWrapper hook; private static IntPtr py_clr_module; + static BorrowedReference ClrModuleReference => new BorrowedReference(py_clr_module); private static IntPtr module_def = IntPtr.Zero; @@ -74,7 +75,7 @@ static void RestoreImport() /// /// Initialization performed on startup of the Python runtime. /// - internal static void Initialize() + internal static unsafe void Initialize() { InitImport(); @@ -86,14 +87,13 @@ internal static void Initialize() py_clr_module = Runtime.PyModule_Create2(module_def, 3); // both dicts are borrowed references - IntPtr mod_dict = Runtime.PyModule_GetDict(py_clr_module); - IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject** - clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); + BorrowedReference mod_dict = Runtime.PyModule_GetDict(ClrModuleReference); + BorrowedReference clr_dict = *Runtime._PyObject_GetDictPtr(root.ObjectReference); Runtime.PyDict_Update(mod_dict, clr_dict); - IntPtr dict = Runtime.PyImport_GetModuleDict(); - Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module); - Runtime.PyDict_SetItemString(dict, "clr", py_clr_module); + BorrowedReference dict = Runtime.PyImport_GetModuleDict(); + Runtime.PyDict_SetItemString(dict, "CLR", ClrModuleReference); + Runtime.PyDict_SetItemString(dict, "clr", ClrModuleReference); } @@ -143,67 +143,62 @@ internal static void RestoreRuntimeData(RuntimeDataStorage storage) /// /// Return the clr python module (new reference) /// - public static IntPtr GetCLRModule(IntPtr? fromList = null) + public static unsafe NewReference GetCLRModule(BorrowedReference fromList = default) { root.InitializePreload(); // update the module dictionary with the contents of the root dictionary root.LoadNames(); - IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module); - IntPtr clr_dict = Runtime._PyObject_GetDictPtr(root.pyHandle); // PyObject** - clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); + BorrowedReference py_mod_dict = Runtime.PyModule_GetDict(ClrModuleReference); + BorrowedReference clr_dict = *Runtime._PyObject_GetDictPtr(root.ObjectReference); Runtime.PyDict_Update(py_mod_dict, clr_dict); // find any items from the from list and get them from the root if they're not // already in the module dictionary - if (fromList != null && fromList != IntPtr.Zero) + if (fromList != null && fromList != default) { - if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) + if (Runtime.PyTuple_Check(fromList)) { - Runtime.XIncref(py_mod_dict); - using (var mod_dict = new PyDict(py_mod_dict)) + using var mod_dict = new PyDict(py_mod_dict); + using var from = new PyTuple(fromList); + foreach (PyObject item in from) { - Runtime.XIncref(fromList.GetValueOrDefault()); - using (var from = new PyTuple(fromList.GetValueOrDefault())) + if (mod_dict.HasKey(item)) { - foreach (PyObject item in from) - { - if (mod_dict.HasKey(item)) - { - continue; - } - - var s = item.AsManagedObject(typeof(string)) as string; - if (s == null) - { - continue; - } - - ManagedType attr = root.GetAttribute(s, true); - if (attr == null) - { - continue; - } - - Runtime.XIncref(attr.pyHandle); - using (var obj = new PyObject(attr.pyHandle)) - { - mod_dict.SetItem(s, obj); - } - } + continue; + } + + var s = item.AsManagedObject(typeof(string)) as string; + if (s == null) + { + continue; + } + + ManagedType attr = root.GetAttribute(s, true); + if (attr == null) + { + continue; + } + + Runtime.XIncref(attr.pyHandle); + using (var obj = new PyObject(attr.pyHandle)) + { + mod_dict.SetItem(s, obj); } } } } Runtime.XIncref(py_clr_module); - return py_clr_module; + return NewReference.DangerousFromPointer(py_clr_module); } /// /// The actual import hook that ties Python to the managed world. /// - public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) + public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw) { + var args = new BorrowedReference(argsRaw); + // Replacement for the builtin __import__. The original import // hook is saved as this.py_import. This version handles CLR // import and defers to the normal builtin for everything else. @@ -214,9 +209,8 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) return Exceptions.RaiseTypeError("__import__() takes at least 1 argument (0 given)"); } - // borrowed reference - IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0); - if (py_mod_name == IntPtr.Zero || + BorrowedReference py_mod_name = Runtime.PyTuple_GetItem(args, 0); + if (py_mod_name.IsNull || !Runtime.IsStringType(py_mod_name)) { return Exceptions.RaiseTypeError("string expected"); @@ -225,12 +219,12 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) // Check whether the import is of the form 'from x import y'. // This determines whether we return the head or tail module. - IntPtr fromList = IntPtr.Zero; + BorrowedReference fromList = default; var fromlist = false; if (num_args >= 4) { fromList = Runtime.PyTuple_GetItem(args, 3); - if (fromList != IntPtr.Zero && + if (fromList != default && Runtime.PyObject_IsTrue(fromList) == 1) { fromlist = true; @@ -243,16 +237,16 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) // the module. if (mod_name == "clr") { - IntPtr clr_module = GetCLRModule(fromList); - if (clr_module != IntPtr.Zero) + NewReference clr_module = GetCLRModule(fromList); + if (!clr_module.IsNull()) { - IntPtr sys_modules = Runtime.PyImport_GetModuleDict(); - if (sys_modules != IntPtr.Zero) + BorrowedReference sys_modules = Runtime.PyImport_GetModuleDict(); + if (!sys_modules.IsNull) { Runtime.PyDict_SetItemString(sys_modules, "clr", clr_module); } } - return clr_module; + return clr_module.DangerousMoveToPointerOrNull(); } string realname = mod_name; @@ -265,7 +259,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) // Turns out that the AssemblyManager.ResolveHandler() checks to see if any // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very // little sense to me. - IntPtr res = Runtime.PyObject_Call(py_import, args, kw); + IntPtr res = Runtime.PyObject_Call(py_import, args.DangerousGetAddress(), kw); if (res != IntPtr.Zero) { // There was no error. @@ -300,10 +294,10 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) // See if sys.modules for this interpreter already has the // requested module. If so, just return the existing module. - IntPtr modules = Runtime.PyImport_GetModuleDict(); - IntPtr module = Runtime.PyDict_GetItem(modules, py_mod_name); + BorrowedReference modules = Runtime.PyImport_GetModuleDict(); + BorrowedReference module = Runtime.PyDict_GetItem(modules, py_mod_name); - if (module != IntPtr.Zero) + if (module != default) { if (fromlist) { @@ -312,16 +306,14 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) var mod = ManagedType.GetManagedObject(module) as ModuleObject; mod?.LoadNames(); } - Runtime.XIncref(module); - return module; + return new NewReference(module).DangerousMoveToPointer(); } if (clr_prefix != null) { - return GetCLRModule(fromList); + return GetCLRModule(fromList).DangerousMoveToPointerOrNull(); } module = Runtime.PyDict_GetItemString(modules, names[0]); - Runtime.XIncref(module); - return module; + return new NewReference(module, canBeNull: true).DangerousMoveToPointer(); } Exceptions.Clear(); @@ -358,12 +350,12 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) } // Add the module to sys.modules - Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.pyHandle); + Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.ObjectReference); // If imported from CLR add clr. to sys.modules as well if (clr_prefix != null) { - Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.pyHandle); + Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.ObjectReference); } } @@ -380,7 +372,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) } } - private static bool IsLoadAll(IntPtr fromList) + private static bool IsLoadAll(BorrowedReference fromList) { if (CLRModule.preload) { @@ -390,10 +382,8 @@ private static bool IsLoadAll(IntPtr fromList) { return false; } - IntPtr fp = Runtime.PySequence_GetItem(fromList, 0); - bool res = Runtime.GetManagedString(fp) == "*"; - Runtime.XDecref(fp); - return res; + using var fp = Runtime.PySequence_GetItem(fromList, 0); + return Runtime.GetManagedString(fp) == "*"; } } } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index ff9a98622..0f56f77d9 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -206,8 +206,9 @@ public static int Size(IntPtr pyType) public static int ob_type; private static readonly int size; - private static bool IsException(IntPtr pyObject) + private static bool IsException(IntPtr pyObjectPtr) { + var pyObject = new BorrowedReference(pyObjectPtr); var type = Runtime.PyObject_TYPE(pyObject); return Runtime.PyType_IsSameAsOrSubtype(type, ofType: Exceptions.BaseException) || Runtime.PyType_IsSameAsOrSubtype(type, ofType: Runtime.PyTypeType) diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index b4baef835..09e8a3be2 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -27,6 +27,8 @@ internal enum TrackTypes internal IntPtr pyHandle; // PyObject * internal IntPtr tpHandle; // PyType * + internal BorrowedReference ObjectReference => new BorrowedReference(pyHandle); + private static readonly Dictionary _managedObjs = new Dictionary(); internal void IncrRefCount() @@ -138,6 +140,8 @@ internal static ManagedType GetManagedObjectErr(IntPtr ob) } + internal static bool IsManagedType(BorrowedReference ob) + => IsManagedType(ob.DangerousGetAddressOrNull()); internal static bool IsManagedType(IntPtr ob) { if (ob != IntPtr.Zero) diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index 07dd20e55..3fdd99b9a 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -18,6 +18,7 @@ internal class ModuleObject : ExtensionType internal string moduleName; internal IntPtr dict; + internal BorrowedReference DictRef => new BorrowedReference(dict); protected string _namespace; public ModuleObject(string name) @@ -44,17 +45,14 @@ public ModuleObject(string name) } dict = Runtime.PyDict_New(); - IntPtr pyname = Runtime.PyString_FromString(moduleName); - IntPtr pyfilename = Runtime.PyString_FromString(filename); - IntPtr pydocstring = Runtime.PyString_FromString(docstring); - IntPtr pycls = TypeManager.GetTypeHandle(GetType()); - Runtime.PyDict_SetItem(dict, PyIdentifier.__name__, pyname); - Runtime.PyDict_SetItem(dict, PyIdentifier.__file__, pyfilename); - Runtime.PyDict_SetItem(dict, PyIdentifier.__doc__, pydocstring); - Runtime.PyDict_SetItem(dict, PyIdentifier.__class__, pycls); - Runtime.XDecref(pyname); - Runtime.XDecref(pyfilename); - Runtime.XDecref(pydocstring); + using var pyname = NewReference.DangerousFromPointer(Runtime.PyString_FromString(moduleName)); + using var pyfilename = NewReference.DangerousFromPointer(Runtime.PyString_FromString(filename)); + using var pydocstring = NewReference.DangerousFromPointer(Runtime.PyString_FromString(docstring)); + BorrowedReference pycls = TypeManager.GetTypeReference(GetType()); + Runtime.PyDict_SetItem(DictRef, PyIdentifier.__name__, pyname); + Runtime.PyDict_SetItem(DictRef, PyIdentifier.__file__, pyfilename); + Runtime.PyDict_SetItem(DictRef, PyIdentifier.__doc__, pydocstring); + Runtime.PyDict_SetItem(DictRef, PyIdentifier.__class__, pycls); Runtime.XIncref(dict); SetObjectDict(pyHandle, dict); @@ -177,9 +175,9 @@ public void LoadNames() { continue; } - IntPtr attr = Runtime.PyDict_GetItemString(dict, name); + BorrowedReference attr = Runtime.PyDict_GetItemString(DictRef, name); // If __dict__ has already set a custom property, skip it. - if (attr != IntPtr.Zero) + if (!attr.IsNull) { continue; } @@ -344,7 +342,7 @@ protected override void OnSave(InterDomainContext context) // destroy the cache(s) foreach (var pair in cache) { - if ((Runtime.PyDict_DelItemString(dict, pair.Key) == -1) && + if ((Runtime.PyDict_DelItemString(DictRef, pair.Key) == -1) && (Exceptions.ExceptionMatches(Exceptions.KeyError))) { // Trying to remove a key that's not in the dictionary diff --git a/src/runtime/native/PyCompilerFlags.cs b/src/runtime/native/PyCompilerFlags.cs new file mode 100644 index 000000000..9e8242c58 --- /dev/null +++ b/src/runtime/native/PyCompilerFlags.cs @@ -0,0 +1,13 @@ +using System; + +namespace Python.Runtime.Native +{ + [Flags] + enum PyCompilerFlags + { + SOURCE_IS_UTF8 = 0x0100, + DONT_IMPLY_DEDENT = 0x0200, + ONLY_AST = 0x0400, + IGNORE_COOKIE = 0x0800, + } +} diff --git a/src/runtime/native/StrPtr.cs b/src/runtime/native/StrPtr.cs new file mode 100644 index 000000000..99aa35ddd --- /dev/null +++ b/src/runtime/native/StrPtr.cs @@ -0,0 +1,73 @@ +#nullable enable +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Python.Runtime.Native +{ + [StructLayout(LayoutKind.Sequential)] + struct StrPtr : IDisposable + { + public IntPtr RawPointer { get; set; } + unsafe byte* Bytes => (byte*)this.RawPointer; + + public unsafe StrPtr(string value, Encoding encoding) + { + if (value is null) throw new ArgumentNullException(nameof(value)); + if (encoding is null) throw new ArgumentNullException(nameof(encoding)); + + var bytes = encoding.GetBytes(value); + this.RawPointer = Marshal.AllocHGlobal(checked(bytes.Length + 1)); + try + { + Marshal.Copy(bytes, 0, this.RawPointer, bytes.Length); + this.Bytes[bytes.Length] = 0; + } + catch + { + this.Dispose(); + throw; + } + } + + public unsafe string? ToString(Encoding encoding) + { + if (encoding is null) throw new ArgumentNullException(nameof(encoding)); + if (this.RawPointer == IntPtr.Zero) return null; + + return encoding.GetString((byte*)this.RawPointer, byteCount: checked((int)this.ByteCount)); + } + + public unsafe nuint ByteCount + { + get + { + if (this.RawPointer == IntPtr.Zero) throw new NullReferenceException(); + + nuint zeroIndex = 0; + while (this.Bytes[zeroIndex] != 0) + { + zeroIndex++; + } + return zeroIndex; + } + } + + public void Dispose() + { + if (this.RawPointer == IntPtr.Zero) + return; + + Marshal.FreeHGlobal(this.RawPointer); + this.RawPointer = IntPtr.Zero; + } + + internal static Encoding GetEncodingByPythonName(string pyEncodingName) + { + // https://stackoverflow.com/a/7798749/231238 + if (pyEncodingName == "mbcs") return Encoding.Default; + + return Encoding.GetEncoding(pyEncodingName); + } + } +} diff --git a/src/runtime/platform/LibraryLoader.cs b/src/runtime/platform/LibraryLoader.cs index 193dff274..099b9d6cd 100644 --- a/src/runtime/platform/LibraryLoader.cs +++ b/src/runtime/platform/LibraryLoader.cs @@ -1,5 +1,7 @@ using System; using System.ComponentModel; +using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; namespace Python.Runtime.Platform @@ -49,13 +51,12 @@ class LinuxLoader : ILibraryLoader public IntPtr Load(string dllToLoad) { - var filename = $"lib{dllToLoad}.so"; ClearError(); - var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + var res = dlopen(dllToLoad, RTLD_NOW | RTLD_GLOBAL); if (res == IntPtr.Zero) { var err = GetError(); - throw new DllNotFoundException($"Could not load {filename} with flags RTLD_NOW | RTLD_GLOBAL: {err}"); + throw new DllNotFoundException($"Could not load {dllToLoad} with flags RTLD_NOW | RTLD_GLOBAL: {err}"); } return res; @@ -120,13 +121,12 @@ class DarwinLoader : ILibraryLoader public IntPtr Load(string dllToLoad) { - var filename = $"lib{dllToLoad}.dylib"; ClearError(); - var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + var res = dlopen(dllToLoad, RTLD_NOW | RTLD_GLOBAL); if (res == IntPtr.Zero) { var err = GetError(); - throw new DllNotFoundException($"Could not load {filename} with flags RTLD_NOW | RTLD_GLOBAL: {err}"); + throw new DllNotFoundException($"Could not load {dllToLoad} with flags RTLD_NOW | RTLD_GLOBAL: {err}"); } return res; @@ -197,6 +197,15 @@ public IntPtr Load(string dllToLoad) public IntPtr GetFunction(IntPtr hModule, string procedureName) { + if (hModule == IntPtr.Zero) + { + foreach(var module in GetAllModules()) + { + var func = GetProcAddress(module, procedureName); + if (func != IntPtr.Zero) return func; + } + } + var res = WindowsLoader.GetProcAddress(hModule, procedureName); if (res == IntPtr.Zero) throw new MissingMethodException($"Failed to load symbol {procedureName}", new Win32Exception()); @@ -205,6 +214,24 @@ public IntPtr GetFunction(IntPtr hModule, string procedureName) public void Free(IntPtr hModule) => WindowsLoader.FreeLibrary(hModule); + static IntPtr[] GetAllModules() + { + var self = Process.GetCurrentProcess().Handle; + + uint bytes = 0; + var result = new IntPtr[0]; + if (!EnumProcessModules(self, result, bytes, out var needsBytes)) + throw new Win32Exception(); + while (bytes < needsBytes) + { + bytes = needsBytes; + result = new IntPtr[bytes / IntPtr.Size]; + if (!EnumProcessModules(self, result, bytes, out needsBytes)) + throw new Win32Exception(); + } + return result.Take((int)(needsBytes / IntPtr.Size)).ToArray(); + } + [DllImport(NativeDll, SetLastError = true)] static extern IntPtr LoadLibrary(string dllToLoad); @@ -213,5 +240,8 @@ public IntPtr GetFunction(IntPtr hModule, string procedureName) [DllImport(NativeDll)] static extern bool FreeLibrary(IntPtr hModule); + + [DllImport("Psapi.dll", SetLastError = true)] + static extern bool EnumProcessModules(IntPtr hProcess, [In, Out] IntPtr[] lphModule, uint lphModuleByteCount, out uint byteCountNeeded); } } diff --git a/src/runtime/platform/NativeCodePage.cs b/src/runtime/platform/NativeCodePage.cs deleted file mode 100644 index b6fe89425..000000000 --- a/src/runtime/platform/NativeCodePage.cs +++ /dev/null @@ -1,226 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace Python.Runtime.Platform -{ - class NativeCodePageHelper - { - /// - /// Initialized by InitializeNativeCodePage. - /// - /// This points to a page of memory allocated using mmap or VirtualAlloc - /// (depending on the system), and marked read and execute (not write). - /// Very much on purpose, the page is *not* released on a shutdown and - /// is instead leaked. See the TestDomainReload test case. - /// - /// The contents of the page are two native functions: one that returns 0, - /// one that returns 1. - /// - /// If python didn't keep its gc list through a Py_Finalize we could remove - /// this entire section. - /// - internal static IntPtr NativeCodePage = IntPtr.Zero; - - - /// - /// Structure to describe native code. - /// - /// Use NativeCode.Active to get the native code for the current platform. - /// - /// Generate the code by creating the following C code: - /// - /// int Return0() { return 0; } - /// int Return1() { return 1; } - /// - /// Then compiling on the target platform, e.g. with gcc or clang: - /// cc -c -fomit-frame-pointer -O2 foo.c - /// And then analyzing the resulting functions with a hex editor, e.g.: - /// objdump -disassemble foo.o - /// - internal class NativeCode - { - /// - /// The code, as a string of bytes. - /// - public byte[] Code { get; private set; } - - /// - /// Where does the "return 0" function start? - /// - public int Return0 { get; private set; } - - /// - /// Where does the "return 1" function start? - /// - public int Return1 { get; private set; } - - public static NativeCode Active - { - get - { - switch (RuntimeInformation.ProcessArchitecture) - { - case Architecture.X86: - return I386; - case Architecture.X64: - return X86_64; - default: - return null; - } - } - } - - /// - /// Code for x86_64. See the class comment for how it was generated. - /// - public static readonly NativeCode X86_64 = new NativeCode() - { - Return0 = 0x10, - Return1 = 0, - Code = new byte[] - { - // First Return1: - 0xb8, 0x01, 0x00, 0x00, 0x00, // movl $1, %eax - 0xc3, // ret - - // Now some padding so that Return0 can be 16-byte-aligned. - // I put Return1 first so there's not as much padding to type in. - 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, // nop - - // Now Return0. - 0x31, 0xc0, // xorl %eax, %eax - 0xc3, // ret - } - }; - - /// - /// Code for X86. - /// - /// It's bitwise identical to X86_64, so we just point to it. - /// - /// - public static readonly NativeCode I386 = X86_64; - } - - /// - /// Platform-dependent mmap and mprotect. - /// - internal interface IMemoryMapper - { - /// - /// Map at least numBytes of memory. Mark the page read-write (but not exec). - /// - IntPtr MapWriteable(int numBytes); - - /// - /// Sets the mapped memory to be read-exec (but not write). - /// - void SetReadExec(IntPtr mappedMemory, int numBytes); - } - - class WindowsMemoryMapper : IMemoryMapper - { - const UInt32 MEM_COMMIT = 0x1000; - const UInt32 MEM_RESERVE = 0x2000; - const UInt32 PAGE_READWRITE = 0x04; - const UInt32 PAGE_EXECUTE_READ = 0x20; - - [DllImport("kernel32.dll")] - static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, UInt32 flAllocationType, UInt32 flProtect); - - [DllImport("kernel32.dll")] - static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, UInt32 flNewProtect, out UInt32 lpflOldProtect); - - public IntPtr MapWriteable(int numBytes) - { - return VirtualAlloc(IntPtr.Zero, new IntPtr(numBytes), - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - } - - public void SetReadExec(IntPtr mappedMemory, int numBytes) - { - UInt32 _; - VirtualProtect(mappedMemory, new IntPtr(numBytes), PAGE_EXECUTE_READ, out _); - } - } - - class UnixMemoryMapper : IMemoryMapper - { - const int PROT_READ = 0x1; - const int PROT_WRITE = 0x2; - const int PROT_EXEC = 0x4; - - const int MAP_PRIVATE = 0x2; - int MAP_ANONYMOUS - { - get - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return 0x20; - } - else - { - // OSX, FreeBSD - return 0x1000; - } - } - } - - [DllImport("libc")] - static extern IntPtr mmap(IntPtr addr, IntPtr len, int prot, int flags, int fd, IntPtr offset); - - [DllImport("libc")] - static extern int mprotect(IntPtr addr, IntPtr len, int prot); - - public IntPtr MapWriteable(int numBytes) - { - // MAP_PRIVATE must be set on linux, even though MAP_ANON implies it. - // It doesn't hurt on darwin, so just do it. - return mmap(IntPtr.Zero, new IntPtr(numBytes), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, IntPtr.Zero); - } - - public void SetReadExec(IntPtr mappedMemory, int numBytes) - { - mprotect(mappedMemory, new IntPtr(numBytes), PROT_READ | PROT_EXEC); - } - } - - internal static IMemoryMapper CreateMemoryMapper() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return new WindowsMemoryMapper(); - } - else - { - // Linux, OSX, FreeBSD - return new UnixMemoryMapper(); - } - } - - /// - /// Initializes the native code page. - /// - /// Safe to call if we already initialized (this function is idempotent). - /// - /// - internal static void InitializeNativeCodePage() - { - // Do nothing if we already initialized. - if (NativeCodePage != IntPtr.Zero) - { - return; - } - - // Allocate the page, write the native code into it, then set it - // to be executable. - IMemoryMapper mapper = CreateMemoryMapper(); - int codeLength = NativeCode.Active.Code.Length; - NativeCodePage = mapper.MapWriteable(codeLength); - Marshal.Copy(NativeCode.Active.Code, 0, NativeCodePage, codeLength); - mapper.SetReadExec(NativeCodePage, codeLength); - } - } -} diff --git a/src/runtime/platform/Types.cs b/src/runtime/platform/Types.cs deleted file mode 100644 index 15235da5a..000000000 --- a/src/runtime/platform/Types.cs +++ /dev/null @@ -1,192 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Python.Runtime.Platform -{ - public enum MachineType - { - i386, - x86_64, - armv7l, - armv8, - aarch64, - Other - }; - - /// - /// Operating system type as reported by Python. - /// - public enum OperatingSystemType - { - Windows, - Darwin, - Linux, - Other - } - - - static class SystemInfo - { - public static MachineType GetMachineType() - { - return Runtime.IsWindows ? GetMachineType_Windows() : GetMachineType_Unix(); - } - - public static string GetArchitecture() - { - return Runtime.IsWindows ? GetArchName_Windows() : GetArchName_Unix(); - } - - public static OperatingSystemType GetSystemType() - { - if (Runtime.IsWindows) - { - return OperatingSystemType.Windows; - } - switch (PythonEngine.Platform) - { - case "linux": - return OperatingSystemType.Linux; - - case "darwin": - return OperatingSystemType.Darwin; - - default: - return OperatingSystemType.Other; - } - } - - #region WINDOWS - - static string GetArchName_Windows() - { - // https://docs.microsoft.com/en-us/windows/win32/winprog64/wow64-implementation-details - return Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); - } - - static MachineType GetMachineType_Windows() - { - if (Runtime.Is32Bit) - { - return MachineType.i386; - } - switch (GetArchName_Windows()) - { - case "AMD64": - return MachineType.x86_64; - case "ARM64": - return MachineType.aarch64; - default: - return MachineType.Other; - } - } - - #endregion - - #region UNIX - - - [StructLayout(LayoutKind.Sequential)] - unsafe struct utsname_linux - { - const int NameLength = 65; - - /* Name of the implementation of the operating system. */ - public fixed byte sysname[NameLength]; - - /* Name of this node on the network. */ - public fixed byte nodename[NameLength]; - - /* Current release level of this implementation. */ - public fixed byte release[NameLength]; - - /* Current version level of this release. */ - public fixed byte version[NameLength]; - - /* Name of the hardware type the system is running on. */ - public fixed byte machine[NameLength]; - - // GNU extension - fixed byte domainname[NameLength]; /* NIS or YP domain name */ - } - - [StructLayout(LayoutKind.Sequential)] - unsafe struct utsname_darwin - { - const int NameLength = 256; - - /* Name of the implementation of the operating system. */ - public fixed byte sysname[NameLength]; - - /* Name of this node on the network. */ - public fixed byte nodename[NameLength]; - - /* Current release level of this implementation. */ - public fixed byte release[NameLength]; - - /* Current version level of this release. */ - public fixed byte version[NameLength]; - - /* Name of the hardware type the system is running on. */ - public fixed byte machine[NameLength]; - } - - [DllImport("libc")] - static extern int uname(IntPtr buf); - - - static unsafe string GetArchName_Unix() - { - switch (GetSystemType()) - { - case OperatingSystemType.Linux: - { - var buf = stackalloc utsname_linux[1]; - if (uname((IntPtr)buf) != 0) - { - return null; - } - return Marshal.PtrToStringAnsi((IntPtr)buf->machine); - } - - case OperatingSystemType.Darwin: - { - var buf = stackalloc utsname_darwin[1]; - if (uname((IntPtr)buf) != 0) - { - return null; - } - return Marshal.PtrToStringAnsi((IntPtr)buf->machine); - } - - default: - return null; - } - } - - static unsafe MachineType GetMachineType_Unix() - { - switch (GetArchName_Unix()) - { - case "x86_64": - case "em64t": - return Runtime.Is32Bit ? MachineType.i386 : MachineType.x86_64; - case "i386": - case "i686": - return MachineType.i386; - - case "armv7l": - return MachineType.armv7l; - case "armv8": - return Runtime.Is32Bit ? MachineType.armv7l : MachineType.armv8; - case "aarch64": - return Runtime.Is32Bit ? MachineType.armv7l : MachineType.aarch64; - - default: - return MachineType.Other; - } - } - - #endregion - } -} diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs index ade873f7a..4b850a9f9 100644 --- a/src/runtime/pydict.cs +++ b/src/runtime/pydict.cs @@ -22,6 +22,7 @@ public PyDict(IntPtr ptr) : base(ptr) { } + internal PyDict(BorrowedReference reference) : base(reference) { } /// /// PyDict Constructor @@ -103,12 +104,12 @@ public bool HasKey(string key) /// public PyObject Keys() { - IntPtr items = Runtime.PyDict_Keys(obj); - if (items == IntPtr.Zero) + using var items = Runtime.PyDict_Keys(Reference); + if (items.IsNull()) { throw new PythonException(); } - return new PyObject(items); + return items.MoveToPyObject(); } @@ -137,7 +138,7 @@ public PyObject Values() /// public PyObject Items() { - var items = Runtime.PyDict_Items(this.obj); + var items = Runtime.PyDict_Items(this.Reference); try { if (items.IsNull()) @@ -179,7 +180,7 @@ public PyDict Copy() /// public void Update(PyObject other) { - int result = Runtime.PyDict_Update(obj, other.obj); + int result = Runtime.PyDict_Update(Reference, other.Reference); if (result < 0) { throw new PythonException(); diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs index b07b95de1..a1752ff68 100644 --- a/src/runtime/pyfloat.cs +++ b/src/runtime/pyfloat.cs @@ -66,9 +66,9 @@ private static IntPtr FromString(string value) { using (var s = new PyString(value)) { - IntPtr val = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero); + NewReference val = Runtime.PyFloat_FromString(s.Reference); PythonException.ThrowIfIsNull(val); - return val; + return val.DangerousMoveToPointerOrNull(); } } diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs index f8718cb95..7b02c68e5 100644 --- a/src/runtime/pyint.cs +++ b/src/runtime/pyint.cs @@ -149,7 +149,7 @@ public PyInt(sbyte value) : this((int)value) private static IntPtr FromString(string value) { - IntPtr val = Runtime.PyInt_FromString(value, IntPtr.Zero, 0); + IntPtr val = Runtime.PyLong_FromString(value, IntPtr.Zero, 0); PythonException.ThrowIfIsNull(val); return val; } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index d68a9905b..902d8c734 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -257,7 +257,7 @@ public bool HasAttr(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); - return Runtime.PyObject_HasAttrString(obj, name) != 0; + return Runtime.PyObject_HasAttrString(Reference, name) != 0; } @@ -272,7 +272,7 @@ public bool HasAttr(PyObject name) { if (name == null) throw new ArgumentNullException(nameof(name)); - return Runtime.PyObject_HasAttr(obj, name.obj) != 0; + return Runtime.PyObject_HasAttr(Reference, name.Reference) != 0; } diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index d61573733..72cb9f247 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -30,11 +30,13 @@ public class PyScope : DynamicObject, IDisposable /// the python Module object the scope associated with. /// internal IntPtr obj; + internal BorrowedReference Reference => new BorrowedReference(obj); /// /// the variable dict of the scope. /// internal readonly IntPtr variables; + internal BorrowedReference VarsRef => new BorrowedReference(variables); private bool _isDisposed; private bool _finalized = false; @@ -56,20 +58,20 @@ public class PyScope : DynamicObject, IDisposable /// /// Create a scope based on a Python Module. /// - internal PyScope(IntPtr ptr, PyScopeManager manager) + internal PyScope(ref NewReference ptr, PyScopeManager manager) { if (!Runtime.PyType_IsSubtype(Runtime.PyObject_TYPE(ptr), Runtime.PyModuleType)) { throw new PyScopeException("object is not a module"); } Manager = manager ?? PyScopeManager.Global; - obj = ptr; + obj = ptr.DangerousMoveToPointer(); //Refcount of the variables not increase - variables = Runtime.PyModule_GetDict(obj); + variables = Runtime.PyModule_GetDict(Reference).DangerousGetAddress(); PythonException.ThrowIfIsNull(variables); int res = Runtime.PyDict_SetItem( - variables, PyIdentifier.__builtins__, + VarsRef, PyIdentifier.__builtins__, Runtime.PyEval_GetBuiltins() ); PythonException.ThrowIfIsNotZero(res); @@ -184,7 +186,7 @@ public void ImportAll(string name) /// public void ImportAll(PyScope scope) { - int result = Runtime.PyDict_Update(variables, scope.variables); + int result = Runtime.PyDict_Update(VarsRef, scope.VarsRef); if (result < 0) { throw new PythonException(); @@ -203,8 +205,8 @@ public void ImportAll(PyObject module) { throw new PyScopeException("object is not a module"); } - var module_dict = Runtime.PyModule_GetDict(module.obj); - int result = Runtime.PyDict_Update(variables, module_dict); + var module_dict = Runtime.PyModule_GetDict(module.Reference); + int result = Runtime.PyDict_Update(VarsRef, module_dict); if (result < 0) { throw new PythonException(); @@ -219,7 +221,7 @@ public void ImportAll(PyObject module) /// public void ImportAll(PyDict dict) { - int result = Runtime.PyDict_Update(variables, dict.obj); + int result = Runtime.PyDict_Update(VarsRef, dict.Reference); if (result < 0) { throw new PythonException(); @@ -277,10 +279,10 @@ public T Execute(PyObject script, PyDict locals = null) public PyObject Eval(string code, PyDict locals = null) { Check(); - IntPtr _locals = locals == null ? variables : locals.obj; + BorrowedReference _locals = locals == null ? VarsRef : locals.Reference; NewReference reference = Runtime.PyRun_String( - code, RunFlagType.Eval, variables, _locals + code, RunFlagType.Eval, VarsRef, _locals ); PythonException.ThrowIfIsNull(reference); return reference.MoveToPyObject(); @@ -310,11 +312,11 @@ public T Eval(string code, PyDict locals = null) public void Exec(string code, PyDict locals = null) { Check(); - IntPtr _locals = locals == null ? variables : locals.obj; - Exec(code, variables, _locals); + BorrowedReference _locals = locals == null ? VarsRef : locals.Reference; + Exec(code, VarsRef, _locals); } - private void Exec(string code, IntPtr _globals, IntPtr _locals) + private void Exec(string code, BorrowedReference _globals, BorrowedReference _locals) { NewReference reference = Runtime.PyRun_String( code, RunFlagType.File, _globals, _locals @@ -551,11 +553,11 @@ internal PyScope NewScope(string name) name = ""; } var module = Runtime.PyModule_New(name); - if (module == IntPtr.Zero) + if (module.IsNull()) { throw new PythonException(); } - return new PyScope(module, this); + return new PyScope(ref module, this); } /// diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 781d345e7..b5334fabc 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -211,15 +211,15 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, } // Load the clr.py resource into the clr module - IntPtr clr = Python.Runtime.ImportHook.GetCLRModule(); - IntPtr clr_dict = Runtime.PyModule_GetDict(clr); + NewReference clr = Python.Runtime.ImportHook.GetCLRModule(); + BorrowedReference clr_dict = Runtime.PyModule_GetDict(clr); var locals = new PyDict(); try { - IntPtr module = Runtime.PyImport_AddModule("clr._extras"); - IntPtr module_globals = Runtime.PyModule_GetDict(module); - IntPtr builtins = Runtime.PyEval_GetBuiltins(); + BorrowedReference module = Runtime.PyImport_AddModule("clr._extras"); + BorrowedReference module_globals = Runtime.PyModule_GetDict(module); + BorrowedReference builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); Assembly assembly = Assembly.GetExecutingAssembly(); @@ -228,7 +228,7 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, { // add the contents of clr.py to the module string clr_py = reader.ReadToEnd(); - Exec(clr_py, module_globals, locals.Handle); + Exec(clr_py, module_globals, locals.Reference); } // add the imported module to the clr module, and copy the API functions @@ -240,7 +240,7 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, if (!key.ToString().StartsWith("_") || key.ToString().Equals("__version__")) { PyObject value = locals[key]; - Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle); + Runtime.PyDict_SetItem(clr_dict, key.Reference, value.Reference); value.Dispose(); } key.Dispose(); @@ -305,7 +305,8 @@ public static IntPtr InitExt() return IntPtr.Zero; } - return Python.Runtime.ImportHook.GetCLRModule(); + return Python.Runtime.ImportHook.GetCLRModule() + .DangerousMoveToPointerOrNull(); } /// @@ -544,7 +545,9 @@ public static PyObject Compile(string code, string filename = "", RunFlagType mo /// public static PyObject Eval(string code, IntPtr? globals = null, IntPtr? locals = null) { - PyObject result = RunString(code, globals, locals, RunFlagType.Eval); + var globalsRef = new BorrowedReference(globals.GetValueOrDefault()); + var localsRef = new BorrowedReference(locals.GetValueOrDefault()); + PyObject result = RunString(code, globalsRef, localsRef, RunFlagType.Eval); return result; } @@ -558,12 +561,27 @@ public static PyObject Eval(string code, IntPtr? globals = null, IntPtr? locals /// public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = null) { - using (PyObject result = RunString(code, globals, locals, RunFlagType.File)) + var globalsRef = new BorrowedReference(globals.GetValueOrDefault()); + var localsRef = new BorrowedReference(locals.GetValueOrDefault()); + using PyObject result = RunString(code, globalsRef, localsRef, RunFlagType.File); + if (result.obj != Runtime.PyNone) { - if (result.obj != Runtime.PyNone) - { - throw new PythonException(); - } + throw new PythonException(); + } + } + /// + /// Exec Method + /// + /// + /// Run a string containing Python code. + /// It's a subset of Python exec function. + /// + internal static void Exec(string code, BorrowedReference globals, BorrowedReference locals = default) + { + using PyObject result = RunString(code, globals: globals, locals: locals, RunFlagType.File); + if (result.obj != Runtime.PyNone) + { + throw new PythonException(); } } @@ -599,7 +617,7 @@ public static int Interrupt(ulong pythonThreadID) [Obsolete("RunString is deprecated and will be removed. Use Exec/Eval/RunSimpleString instead.")] public static PyObject RunString(string code, IntPtr? globals = null, IntPtr? locals = null) { - return RunString(code, globals, locals, RunFlagType.File); + return RunString(code, new BorrowedReference(globals.GetValueOrDefault()), new BorrowedReference(locals.GetValueOrDefault()), RunFlagType.File); } /// @@ -610,20 +628,19 @@ public static PyObject RunString(string code, IntPtr? globals = null, IntPtr? lo /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// - internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, RunFlagType flag) + internal static PyObject RunString(string code, BorrowedReference globals, BorrowedReference locals, RunFlagType flag) { - var borrowedGlobals = true; - if (globals == null) + NewReference tempGlobals = default; + if (globals.IsNull) { globals = Runtime.PyEval_GetGlobals(); - if (globals == IntPtr.Zero) + if (globals.IsNull) { - globals = Runtime.PyDict_New(); + globals = tempGlobals = NewReference.DangerousFromPointer(Runtime.PyDict_New()); Runtime.PyDict_SetItem( - globals.Value, PyIdentifier.__builtins__, + globals, PyIdentifier.__builtins__, Runtime.PyEval_GetBuiltins() ); - borrowedGlobals = false; } } @@ -635,17 +652,14 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, try { NewReference result = Runtime.PyRun_String( - code, flag, globals.Value, locals.Value + code, flag, globals, locals ); PythonException.ThrowIfIsNull(result); return result.MoveToPyObject(); } finally { - if (!borrowedGlobals) - { - Runtime.XDecref(globals.Value); - } + tempGlobals.Dispose(); } } } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index c754b80b5..990ac2a9f 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -9,6 +9,7 @@ using Python.Runtime.Native; using Python.Runtime.Platform; using System.Linq; +using static System.FormattableString; namespace Python.Runtime { @@ -17,51 +18,48 @@ namespace Python.Runtime /// the responsibility of the caller to have acquired the GIL /// before calling any of these methods. /// - public class Runtime + public unsafe 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 + public static string PythonDLL + { + get => _PythonDll; + set + { + if (_isInitialized) + throw new InvalidOperationException("This property must be set before runtime is initialized"); + _PythonDll = value; + } + } -#if WINDOWS - internal const string dllBase = "python3" + _minor; -#else - internal const string dllBase = "python3." + _minor; -#endif + static string _PythonDll = GetDefaultDllName(); + private static string GetDefaultDllName() + { + string dll = Environment.GetEnvironmentVariable("PYTHONNET_PYDLL"); + if (dll is not null) return dll; -#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 + try + { + LibraryLoader.Instance.GetFunction(IntPtr.Zero, "PyUnicode_GetMax"); + return null; + } catch (MissingMethodException) { } - // 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. + string verString = Environment.GetEnvironmentVariable("PYTHONNET_PYVER"); + if (!Version.TryParse(verString, out var version)) return null; - public static readonly string PythonDLL = _PythonDll; + return GetDefaultDllName(version); + } -#if PYTHON_WITHOUT_ENABLE_SHARED && !NETSTANDARD - internal const string _PythonDll = "__Internal"; -#else - internal const string _PythonDll = dllBase + dllWithPyDebug + dllWithPyMalloc; -#endif + private static string GetDefaultDllName(Version version) + { + string prefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib"; + string suffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? Invariant($"{version.Major}{version.Minor}") + : Invariant($"{version.Major}.{version.Minor}"); + string ext = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" + : ".so"; + return prefix + "python" + suffix + ext; + } // set to true when python is finalizing internal static object IsFinalizingLock = new object(); @@ -79,11 +77,6 @@ public class Runtime 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(); @@ -240,7 +233,7 @@ private static void InitPyMembers() () => PyUnicodeType = IntPtr.Zero); XDecref(op); - op = PyBytes_FromString("bytes"); + op = EmptyPyBytes(); SetPyMember(ref PyBytesType, PyObject_Type(op), () => PyBytesType = IntPtr.Zero); XDecref(op); @@ -481,8 +474,8 @@ private static void ClearClrModules() 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); + var name = PyTuple_GetItem(item, 0); + var module = PyTuple_GetItem(item, 1); if (ManagedType.IsManagedType(module)) { PyDict_DelItem(modules, name); @@ -498,7 +491,7 @@ private static void RemoveClrRootModule() PyDictTryDelItem(modules, "clr._extra"); } - private static void PyDictTryDelItem(IntPtr dict, string key) + private static void PyDictTryDelItem(BorrowedReference dict, string key) { if (PyDict_DelItemString(dict, key) == 0) { @@ -528,7 +521,7 @@ private static void MoveClrInstancesOnwershipToPython() 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)) + if (!_PyObject_GC_IS_TRACKED(obj.ObjectReference)) { PyObject_GC_Track(obj.pyHandle); } @@ -788,146 +781,161 @@ internal static unsafe long Refcount(IntPtr op) /// 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); + + internal static void Py_IncRef(IntPtr ob) => Delegates.Py_IncRef(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); + + internal static void Py_DecRef(IntPtr ob) => Delegates.Py_DecRef(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_Initialize(); + + internal static void Py_Initialize() => Delegates.Py_Initialize(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_InitializeEx(int initsigs); + + internal static void Py_InitializeEx(int initsigs) => Delegates.Py_InitializeEx(initsigs); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int Py_IsInitialized(); + + internal static int Py_IsInitialized() => Delegates.Py_IsInitialized(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_Finalize(); + + internal static void Py_Finalize() => Delegates.Py_Finalize(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_NewInterpreter(); + + internal static IntPtr Py_NewInterpreter() => Delegates.Py_NewInterpreter(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_EndInterpreter(IntPtr threadState); + + internal static void Py_EndInterpreter(IntPtr threadState) => Delegates.Py_EndInterpreter(threadState); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyThreadState_New(IntPtr istate); + + internal static IntPtr PyThreadState_New(IntPtr istate) => Delegates.PyThreadState_New(istate); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyThreadState_Get(); + + internal static IntPtr PyThreadState_Get() => Delegates.PyThreadState_Get(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr _PyThreadState_UncheckedGet(); + + internal static IntPtr _PyThreadState_UncheckedGet() => Delegates._PyThreadState_UncheckedGet(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyThread_get_key_value(IntPtr key); + + internal static IntPtr PyThread_get_key_value(IntPtr key) => Delegates.PyThread_get_key_value(key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThread_get_thread_ident(); + + internal static int PyThread_get_thread_ident() => Delegates.PyThread_get_thread_ident(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThread_set_key_value(IntPtr key, IntPtr value); + + internal static int PyThread_set_key_value(IntPtr key, IntPtr value) => Delegates.PyThread_set_key_value(key, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyThreadState_Swap(IntPtr key); + + internal static IntPtr PyThreadState_Swap(IntPtr key) => Delegates.PyThreadState_Swap(key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyGILState_Ensure(); + + internal static IntPtr PyGILState_Ensure() => Delegates.PyGILState_Ensure(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyGILState_Release(IntPtr gs); + + internal static void PyGILState_Release(IntPtr gs) => Delegates.PyGILState_Release(gs); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyGILState_GetThisThreadState(); + + internal static IntPtr PyGILState_GetThisThreadState() => Delegates.PyGILState_GetThisThreadState(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - public static extern int Py_Main( - int argc, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv - ); + + public static int Py_Main(int argc, string[] argv) + { + var marshaler = StrArrayMarshaler.GetInstance(null); + var argvPtr = marshaler.MarshalManagedToNative(argv); + try + { + return Delegates.Py_Main(argc, argvPtr); + } + finally + { + marshaler.CleanUpNativeData(argvPtr); + } + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_InitThreads(); + internal static void PyEval_InitThreads() => Delegates.PyEval_InitThreads(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyEval_ThreadsInitialized(); + + internal static int PyEval_ThreadsInitialized() => Delegates.PyEval_ThreadsInitialized(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_AcquireLock(); + + internal static void PyEval_AcquireLock() => Delegates.PyEval_AcquireLock(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_ReleaseLock(); + + internal static void PyEval_ReleaseLock() => Delegates.PyEval_ReleaseLock(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_AcquireThread(IntPtr tstate); + + internal static void PyEval_AcquireThread(IntPtr tstate) => Delegates.PyEval_AcquireThread(tstate); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_ReleaseThread(IntPtr tstate); + + internal static void PyEval_ReleaseThread(IntPtr tstate) => Delegates.PyEval_ReleaseThread(tstate); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_SaveThread(); + + internal static IntPtr PyEval_SaveThread() => Delegates.PyEval_SaveThread(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyEval_RestoreThread(IntPtr tstate); + + internal static void PyEval_RestoreThread(IntPtr tstate) => Delegates.PyEval_RestoreThread(tstate); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_GetBuiltins(); + + internal static BorrowedReference PyEval_GetBuiltins() => Delegates.PyEval_GetBuiltins(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_GetGlobals(); + + internal static BorrowedReference PyEval_GetGlobals() => Delegates.PyEval_GetGlobals(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_GetLocals(); + + internal static IntPtr PyEval_GetLocals() => Delegates.PyEval_GetLocals(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetProgramName(); + + internal static IntPtr Py_GetProgramName() => Delegates.Py_GetProgramName(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_SetProgramName(IntPtr name); + + internal static void Py_SetProgramName(IntPtr name) => Delegates.Py_SetProgramName(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetPythonHome(); + + internal static IntPtr Py_GetPythonHome() => Delegates.Py_GetPythonHome(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_SetPythonHome(IntPtr home); + + internal static void Py_SetPythonHome(IntPtr home) => Delegates.Py_SetPythonHome(home); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetPath(); + + internal static IntPtr Py_GetPath() => Delegates.Py_GetPath(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void Py_SetPath(IntPtr home); + + internal static void Py_SetPath(IntPtr home) => Delegates.Py_SetPath(home); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetVersion(); + + internal static IntPtr Py_GetVersion() => Delegates.Py_GetVersion(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetPlatform(); + + internal static IntPtr Py_GetPlatform() => Delegates.Py_GetPlatform(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetCopyright(); + + internal static IntPtr Py_GetCopyright() => Delegates.Py_GetCopyright(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetCompiler(); + + internal static IntPtr Py_GetCompiler() => Delegates.Py_GetCompiler(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_GetBuildInfo(); + + internal static IntPtr Py_GetBuildInfo() => Delegates.Py_GetBuildInfo(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyRun_SimpleString(string code); + const PyCompilerFlags Utf8String = PyCompilerFlags.IGNORE_COOKIE | PyCompilerFlags.SOURCE_IS_UTF8; - [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); + internal static int PyRun_SimpleString(string code) + { + using var codePtr = new StrPtr(code, Encoding.UTF8); + return Delegates.PyRun_SimpleStringFlags(codePtr, Utf8String); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals); + internal static NewReference PyRun_String(string code, RunFlagType st, BorrowedReference globals, BorrowedReference locals) + { + using var codePtr = new StrPtr(code, Encoding.UTF8); + return Delegates.PyRun_StringFlags(codePtr, st, globals, locals, Utf8String); + } + + internal static IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals) => Delegates.PyEval_EvalCode(co, globals, locals); /// /// Return value: New reference. @@ -935,37 +943,24 @@ public static extern int Py_Main( /// internal static IntPtr Py_CompileString(string str, string file, int start) { - return Py_CompileStringFlags(str, file, start, IntPtr.Zero); + using var strPtr = new StrPtr(str, Encoding.UTF8); + using var fileObj = new PyString(file); + return Delegates.Py_CompileStringObject(strPtr, fileObj.Reference, start, Utf8String, -1); } - /// - /// 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) + internal static IntPtr PyImport_ExecCodeModule(string name, IntPtr code) { - return Py_CompileStringExFlags(str, file, start, flags, -1); + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyImport_ExecCodeModule(namePtr, code); } - /// - /// 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); + internal static IntPtr PyCFunction_NewEx(IntPtr ml, IntPtr self, IntPtr mod) => Delegates.PyCFunction_NewEx(ml, self, mod); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw); + + internal static IntPtr PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw) => Delegates.PyCFunction_Call(func, args, kw); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyMethod_New(IntPtr func, IntPtr self, IntPtr cls); + + internal static IntPtr PyMethod_New(IntPtr func, IntPtr self, IntPtr cls) => Delegates.PyMethod_New(func, self, cls); //==================================================================== @@ -1026,44 +1021,62 @@ internal static bool PyObject_IsIterable(IntPtr pointer) 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); + + internal static int PyObject_HasAttrString(BorrowedReference pointer, string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyObject_HasAttrString(pointer, namePtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GetAttrString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name); + internal static IntPtr PyObject_GetAttrString(IntPtr pointer, string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyObject_GetAttrString(pointer, namePtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_SetAttrString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string name, IntPtr value); + + internal static IntPtr PyObject_GetAttrString(IntPtr pointer, StrPtr name) => Delegates.PyObject_GetAttrString(pointer, name); - [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); + internal static int PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyObject_SetAttrString(pointer, namePtr, value); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value); + internal static int PyObject_HasAttr(BorrowedReference pointer, BorrowedReference name) => Delegates.PyObject_HasAttr(pointer, name); - [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); + internal static NewReference PyObject_GetAttr(BorrowedReference pointer, IntPtr name) + => Delegates.PyObject_GetAttr(pointer, new BorrowedReference(name)); + internal static IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name) + => Delegates.PyObject_GetAttr(new BorrowedReference(pointer), new BorrowedReference(name)) + .DangerousMoveToPointerOrNull(); + internal static NewReference PyObject_GetAttr(BorrowedReference pointer, BorrowedReference name) => Delegates.PyObject_GetAttr(pointer, name); - [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); + internal static int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value) => Delegates.PyObject_SetAttr(pointer, name, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw); + + internal static IntPtr PyObject_GetItem(IntPtr pointer, IntPtr key) => Delegates.PyObject_GetItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args); + + internal static int PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value) => Delegates.PyObject_SetItem(pointer, key, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid); + + internal static int PyObject_DelItem(IntPtr pointer, IntPtr key) => Delegates.PyObject_DelItem(pointer, key); + + + internal static IntPtr PyObject_GetIter(IntPtr op) => Delegates.PyObject_GetIter(op); + + + internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw); + + + internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args) => Delegates.PyObject_CallObject(pointer, args); + + + internal static int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid) => Delegates.PyObject_RichCompareBool(value1, value2, opid); internal static int PyObject_Compare(IntPtr value1, IntPtr value2) { @@ -1090,44 +1103,44 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) return -1; } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_IsInstance(IntPtr ob, IntPtr type); + + internal static int PyObject_IsInstance(IntPtr ob, IntPtr type) => Delegates.PyObject_IsInstance(ob, type); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_IsSubclass(IntPtr ob, IntPtr type); + + internal static int PyObject_IsSubclass(IntPtr ob, IntPtr type) => Delegates.PyObject_IsSubclass(ob, type); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyCallable_Check(IntPtr pointer); + + internal static int PyCallable_Check(IntPtr pointer) => Delegates.PyCallable_Check(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 int PyObject_IsTrue(IntPtr pointer) => PyObject_IsTrue(new BorrowedReference(pointer)); + internal static int PyObject_IsTrue(BorrowedReference pointer) => Delegates.PyObject_IsTrue(pointer); + + + internal static int PyObject_Not(IntPtr pointer) => Delegates.PyObject_Not(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); + + private static IntPtr _PyObject_Size(IntPtr pointer) => Delegates._PyObject_Size(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern nint PyObject_Hash(IntPtr op); + + internal static nint PyObject_Hash(IntPtr op) => Delegates.PyObject_Hash(op); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Repr(IntPtr pointer); + + internal static IntPtr PyObject_Repr(IntPtr pointer) => Delegates.PyObject_Repr(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Str(IntPtr pointer); + + internal static IntPtr PyObject_Str(IntPtr pointer) => Delegates.PyObject_Str(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyObject_Str")] - internal static extern IntPtr PyObject_Unicode(IntPtr pointer); + + internal static IntPtr PyObject_Unicode(IntPtr pointer) => Delegates.PyObject_Unicode(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Dir(IntPtr pointer); + + internal static IntPtr PyObject_Dir(IntPtr pointer) => Delegates.PyObject_Dir(pointer); #if PYTHON_WITH_PYDEBUG [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] @@ -1138,49 +1151,51 @@ internal static long PyObject_Size(IntPtr pointer) // Python buffer API //==================================================================== - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_GetBuffer(IntPtr exporter, ref Py_buffer view, int flags); + + internal static int PyObject_GetBuffer(IntPtr exporter, ref Py_buffer view, int flags) => Delegates.PyObject_GetBuffer(exporter, ref view, flags); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyBuffer_Release(ref Py_buffer view); + + internal static void PyBuffer_Release(ref Py_buffer view) => Delegates.PyBuffer_Release(ref view); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - internal static extern IntPtr PyBuffer_SizeFromFormat([MarshalAs(UnmanagedType.LPStr)] string format); + + internal static IntPtr PyBuffer_SizeFromFormat(string format) + { + using var formatPtr = new StrPtr(format, Encoding.ASCII); + return Delegates.PyBuffer_SizeFromFormat(formatPtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyBuffer_IsContiguous(ref Py_buffer view, char order); + internal static int PyBuffer_IsContiguous(ref Py_buffer view, char order) => Delegates.PyBuffer_IsContiguous(ref view, order); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyBuffer_GetPointer(ref Py_buffer view, IntPtr[] indices); + + internal static IntPtr PyBuffer_GetPointer(ref Py_buffer view, IntPtr[] indices) => Delegates.PyBuffer_GetPointer(ref view, indices); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyBuffer_FromContiguous(ref Py_buffer view, IntPtr buf, IntPtr len, char fort); + + internal static int PyBuffer_FromContiguous(ref Py_buffer view, IntPtr buf, IntPtr len, char fort) => Delegates.PyBuffer_FromContiguous(ref view, buf, len, fort); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyBuffer_ToContiguous(IntPtr buf, ref Py_buffer src, IntPtr len, char order); + + internal static int PyBuffer_ToContiguous(IntPtr buf, ref Py_buffer src, IntPtr len, char order) => Delegates.PyBuffer_ToContiguous(buf, ref src, len, order); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyBuffer_FillContiguousStrides(int ndims, IntPtr shape, IntPtr strides, int itemsize, char order); + + internal static void PyBuffer_FillContiguousStrides(int ndims, IntPtr shape, IntPtr strides, int itemsize, char order) => Delegates.PyBuffer_FillContiguousStrides(ndims, shape, strides, itemsize, 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); + + internal static int PyBuffer_FillInfo(ref Py_buffer view, IntPtr exporter, IntPtr buf, IntPtr len, int _readonly, int flags) => Delegates.PyBuffer_FillInfo(ref view, exporter, buf, len, _readonly, flags); //==================================================================== // Python number API //==================================================================== - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyNumber_Long")] - internal static extern IntPtr PyNumber_Int(IntPtr ob); + + internal static IntPtr PyNumber_Int(IntPtr ob) => Delegates.PyNumber_Int(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Long(IntPtr ob); + + internal static IntPtr PyNumber_Long(IntPtr ob) => Delegates.PyNumber_Long(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Float(IntPtr ob); + + internal static IntPtr PyNumber_Float(IntPtr ob) => Delegates.PyNumber_Float(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern bool PyNumber_Check(IntPtr ob); + + internal static bool PyNumber_Check(IntPtr ob) => Delegates.PyNumber_Check(ob); internal static bool PyInt_Check(BorrowedReference ob) => PyObject_TypeCheck(ob, new BorrowedReference(PyIntType)); @@ -1206,33 +1221,26 @@ internal static IntPtr PyInt_FromInt64(long 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); + + private static IntPtr PyInt_FromLong(IntPtr value) => Delegates.PyInt_FromLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromString")] - internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); + + internal static int PyInt_AsLong(IntPtr value) => Delegates.PyInt_AsLong(value); + 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); + + internal static IntPtr PyLong_FromLong(long value) => Delegates.PyLong_FromLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromUnsignedLong")] - internal static extern IntPtr PyLong_FromUnsignedLong32(uint value); + + internal static IntPtr PyLong_FromUnsignedLong32(uint value) => Delegates.PyLong_FromUnsignedLong32(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromUnsignedLong")] - internal static extern IntPtr PyLong_FromUnsignedLong64(ulong value); + + internal static IntPtr PyLong_FromUnsignedLong64(ulong value) => Delegates.PyLong_FromUnsignedLong64(value); internal static IntPtr PyLong_FromUnsignedLong(object value) { @@ -1242,27 +1250,29 @@ internal static IntPtr PyLong_FromUnsignedLong(object value) return PyLong_FromUnsignedLong64(Convert.ToUInt64(value)); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyLong_FromDouble(double value); + + internal static IntPtr PyLong_FromDouble(double value) => Delegates.PyLong_FromDouble(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyLong_FromLongLong(long value); + + internal static IntPtr PyLong_FromLongLong(long value) => Delegates.PyLong_FromLongLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyLong_FromUnsignedLongLong(ulong value); + + internal static IntPtr PyLong_FromUnsignedLongLong(ulong value) => Delegates.PyLong_FromUnsignedLongLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyLong_FromString(string value, IntPtr end, int radix); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsSize_t")] - internal static extern nuint PyLong_AsUnsignedSize_t(IntPtr value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsSsize_t")] - internal static extern nint PyLong_AsSignedSize_t(IntPtr value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsSsize_t")] - internal static extern nint PyLong_AsSignedSize_t(BorrowedReference value); + + internal static IntPtr PyLong_FromString(string value, IntPtr end, int radix) + { + using var valPtr = new StrPtr(value, Encoding.UTF8); + return Delegates.PyLong_FromString(valPtr, end, radix); + } + + + + internal static nuint PyLong_AsUnsignedSize_t(IntPtr value) => Delegates.PyLong_AsUnsignedSize_t(value); + + internal static nint PyLong_AsSignedSize_t(IntPtr value) => Delegates.PyLong_AsSignedSize_t(new BorrowedReference(value)); + + internal static nint PyLong_AsSignedSize_t(BorrowedReference value) => Delegates.PyLong_AsSignedSize_t(value); /// /// This function is a rename of PyLong_AsLongLong, which has a commonly undesired @@ -1272,11 +1282,10 @@ internal static IntPtr PyLong_FromUnsignedLong(object value) /// In most cases you need to check that value is an instance of PyLongObject /// before using this function using . /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsLongLong")] - internal static extern long PyExplicitlyConvertToInt64(IntPtr value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern ulong PyLong_AsUnsignedLongLong(IntPtr value); + + internal static long PyExplicitlyConvertToInt64(IntPtr value) => Delegates.PyExplicitlyConvertToInt64(value); + + internal static ulong PyLong_AsUnsignedLongLong(IntPtr value) => Delegates.PyLong_AsUnsignedLongLong(value); internal static bool PyFloat_Check(IntPtr ob) { @@ -1287,199 +1296,193 @@ internal static bool PyFloat_Check(IntPtr ob) /// 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); + internal static NewReference PyLong_FromVoidPtr(IntPtr p) => Delegates.PyLong_FromVoidPtr(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); + + internal static IntPtr PyLong_AsVoidPtr(BorrowedReference ob) => Delegates.PyLong_AsVoidPtr(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyFloat_FromDouble(double value); + + internal static IntPtr PyFloat_FromDouble(double value) => Delegates.PyFloat_FromDouble(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyFloat_FromString(IntPtr value, IntPtr junk); + + internal static NewReference PyFloat_FromString(BorrowedReference value) => Delegates.PyFloat_FromString(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern double PyFloat_AsDouble(IntPtr ob); + + internal static double PyFloat_AsDouble(IntPtr ob) => Delegates.PyFloat_AsDouble(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Add(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Add(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Add(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Subtract(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Subtract(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Subtract(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Multiply(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Multiply(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Multiply(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_TrueDivide(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_TrueDivide(IntPtr o1, IntPtr o2) => Delegates.PyNumber_TrueDivide(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_And(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_And(IntPtr o1, IntPtr o2) => Delegates.PyNumber_And(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Xor(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Xor(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Xor(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Or(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Or(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Or(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Lshift(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Lshift(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Lshift(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Rshift(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Rshift(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Rshift(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Power(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Power(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Power(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Remainder(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Remainder(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Remainder(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceAdd(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceAdd(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceAdd(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceSubtract(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceSubtract(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceSubtract(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceMultiply(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceMultiply(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceMultiply(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceTrueDivide(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceTrueDivide(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceTrueDivide(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceAnd(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceAnd(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceAnd(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceXor(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceXor(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceXor(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceOr(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceOr(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceOr(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceLshift(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceLshift(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceLshift(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceRshift(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceRshift(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceRshift(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlacePower(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlacePower(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlacePower(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_InPlaceRemainder(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceRemainder(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceRemainder(o1, o2); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Negative(IntPtr o1); + + internal static IntPtr PyNumber_Negative(IntPtr o1) => Delegates.PyNumber_Negative(o1); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Positive(IntPtr o1); + + internal static IntPtr PyNumber_Positive(IntPtr o1) => Delegates.PyNumber_Positive(o1); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Invert(IntPtr o1); + + internal static IntPtr PyNumber_Invert(IntPtr o1) => Delegates.PyNumber_Invert(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 bool PySequence_Check(IntPtr pointer) => Delegates.PySequence_Check(pointer); + + internal static NewReference PySequence_GetItem(BorrowedReference pointer, nint index) => Delegates.PySequence_GetItem(pointer, 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); + + private static int PySequence_SetItem(IntPtr pointer, IntPtr index, IntPtr value) => Delegates.PySequence_SetItem(pointer, index, 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); + + private static int PySequence_DelItem(IntPtr pointer, IntPtr index) => Delegates.PySequence_DelItem(pointer, 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); + + private static IntPtr PySequence_GetSlice(IntPtr pointer, IntPtr i1, IntPtr i2) => Delegates.PySequence_GetSlice(pointer, i1, 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); + + private static int PySequence_SetSlice(IntPtr pointer, IntPtr i1, IntPtr i2, IntPtr v) => Delegates.PySequence_SetSlice(pointer, i1, i2, 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); + + private static int PySequence_DelSlice(IntPtr pointer, IntPtr i1, IntPtr i2) => Delegates.PySequence_DelSlice(pointer, i1, i2); - internal static long PySequence_Size(IntPtr pointer) - { - return (long)_PySequence_Size(pointer); - } + [Obsolete] + internal static nint PySequence_Size(IntPtr pointer) => PySequence_Size(new BorrowedReference(pointer)); + internal static nint PySequence_Size(BorrowedReference pointer) => Delegates.PySequence_Size(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")] - private static extern IntPtr _PySequence_Size(IntPtr pointer); + + internal static int PySequence_Contains(IntPtr pointer, IntPtr item) => Delegates.PySequence_Contains(pointer, item); - [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_Concat(IntPtr pointer, IntPtr other) => Delegates.PySequence_Concat(pointer, 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); + + private static IntPtr PySequence_Repeat(IntPtr pointer, IntPtr count) => Delegates.PySequence_Repeat(pointer, count); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PySequence_Index(IntPtr pointer, IntPtr item); + + internal static int PySequence_Index(IntPtr pointer, IntPtr item) => Delegates.PySequence_Index(pointer, 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); + + private static IntPtr _PySequence_Count(IntPtr pointer, IntPtr value) => Delegates._PySequence_Count(pointer, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PySequence_Tuple(IntPtr pointer); + + internal static IntPtr PySequence_Tuple(IntPtr pointer) => Delegates.PySequence_Tuple(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PySequence_List(IntPtr pointer); + + internal static IntPtr PySequence_List(IntPtr pointer) => Delegates.PySequence_List(pointer); //==================================================================== // Python string API //==================================================================== - + internal static bool IsStringType(BorrowedReference op) + { + BorrowedReference t = PyObject_TYPE(op); + return (t == new BorrowedReference(PyStringType)) + || (t == new BorrowedReference(PyUnicodeType)); + } internal static bool IsStringType(IntPtr op) { IntPtr t = PyObject_TYPE(op); @@ -1493,19 +1496,25 @@ internal static bool PyString_Check(IntPtr ob) internal static IntPtr PyString_FromString(string value) { - return PyUnicode_FromKindAndData(_UCS, value, value.Length); + fixed(char* ptr = value) + return PyUnicode_FromKindAndData(2, (IntPtr)ptr, value.Length); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyBytes_FromString(string op); + + internal static IntPtr EmptyPyBytes() + { + byte* bytes = stackalloc byte[1]; + bytes[0] = 0; + return Delegates.PyBytes_FromString((IntPtr)bytes); + } 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); + + private static IntPtr _PyBytes_Size(IntPtr op) => Delegates._PyBytes_Size(op); internal static IntPtr PyBytes_AS_STRING(IntPtr ob) { @@ -1518,67 +1527,70 @@ 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); + + private static IntPtr PyUnicode_FromStringAndSize(IntPtr value, IntPtr size) => Delegates.PyUnicode_FromStringAndSize(value, size); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyUnicode_AsUTF8(IntPtr unicode); + + internal static IntPtr PyUnicode_AsUTF8(IntPtr unicode) => Delegates.PyUnicode_AsUTF8(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); + + internal static IntPtr PyUnicode_FromObject(IntPtr ob) => Delegates.PyUnicode_FromObject(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); + + internal static IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err) => Delegates.PyUnicode_FromEncodedObject(ob, enc, err); - internal static IntPtr PyUnicode_FromKindAndData(int kind, string s, long size) + internal static IntPtr PyUnicode_FromKindAndData(int kind, IntPtr 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 - ); + + private static IntPtr PyUnicode_FromKindAndData(int kind, IntPtr s, IntPtr size) + => Delegates.PyUnicode_FromKindAndData(kind, s, size); internal static IntPtr PyUnicode_FromUnicode(string s, long size) { - return PyUnicode_FromKindAndData(_UCS, s, size); + fixed(char* ptr = s) + return PyUnicode_FromKindAndData(2, (IntPtr)ptr, size); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyUnicode_GetMax(); + + internal static int PyUnicode_GetMax() => Delegates.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); + + private static IntPtr _PyUnicode_GetSize(IntPtr ob) => Delegates._PyUnicode_GetSize(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyUnicode_AsUnicode(IntPtr ob); + + internal static IntPtr PyUnicode_AsUnicode(IntPtr ob) => Delegates.PyUnicode_AsUnicode(ob); + internal static NewReference PyUnicode_AsUTF16String(BorrowedReference ob) => Delegates.PyUnicode_AsUTF16String(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyUnicode_FromOrdinal(int c); + + + internal static IntPtr PyUnicode_FromOrdinal(int c) => Delegates.PyUnicode_FromOrdinal(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); + + internal static IntPtr PyUnicode_InternFromString(string s) + { + using var ptr = new StrPtr(s, Encoding.UTF8); + return Delegates.PyUnicode_InternFromString(ptr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyUnicode_Compare(IntPtr left, IntPtr right); + internal static int PyUnicode_Compare(IntPtr left, IntPtr right) => Delegates.PyUnicode_Compare(left, right); internal static string GetManagedString(in BorrowedReference borrowedReference) => GetManagedString(borrowedReference.DangerousGetAddress()); @@ -1601,13 +1613,12 @@ internal static string GetManagedString(IntPtr op) if (type == PyUnicodeType) { - IntPtr p = PyUnicode_AsUnicode(op); + using var p = PyUnicode_AsUTF16String(new BorrowedReference(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); + char* codePoints = (char*)PyBytes_AS_STRING(p.DangerousGetAddress()); + return new string(codePoints, + startIndex: 1, // skip BOM + length: length); } return null; @@ -1623,92 +1634,116 @@ internal static bool PyDict_Check(IntPtr ob) return PyObject_TYPE(ob) == PyDictType; } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_New(); + + internal static IntPtr PyDict_New() => Delegates.PyDict_New(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_Next(IntPtr p, out IntPtr ppos, out IntPtr pkey, out IntPtr pvalue); + + internal static int PyDict_Next(IntPtr p, out IntPtr ppos, out IntPtr pkey, out IntPtr pvalue) => Delegates.PyDict_Next(p, out ppos, out pkey, out pvalue); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDictProxy_New(IntPtr dict); + + internal static IntPtr PyDictProxy_New(IntPtr dict) => Delegates.PyDictProxy_New(dict); /// /// Return value: Borrowed reference. - /// Return NULL if the key key is not present, but without setting an exception. + /// Return NULL if the 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); - + internal static IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key) + => Delegates.PyDict_GetItem(new BorrowedReference(pointer), new BorrowedReference(key)) + .DangerousGetAddressOrNull(); /// - /// Return value: Borrowed reference. + /// Return NULL if the key is not present, but without setting an exception. /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_GetItemString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string key); + internal static BorrowedReference PyDict_GetItem(BorrowedReference pointer, BorrowedReference key) => Delegates.PyDict_GetItem(pointer, key); + + internal static BorrowedReference PyDict_GetItemString(BorrowedReference pointer, string key) + { + using var keyStr = new StrPtr(key, Encoding.UTF8); + return Delegates.PyDict_GetItemString(pointer, keyStr); + } + + internal static BorrowedReference PyDict_GetItemWithError(BorrowedReference pointer, BorrowedReference key) => Delegates.PyDict_GetItemWithError(pointer, 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); + [Obsolete] + internal static int PyDict_SetItem(IntPtr dict, IntPtr key, IntPtr value) => Delegates.PyDict_SetItem(new BorrowedReference(dict), new BorrowedReference(key), new BorrowedReference(value)); + /// + /// Return 0 on success or -1 on failure. + /// + internal static int PyDict_SetItem(BorrowedReference dict, IntPtr key, BorrowedReference value) => Delegates.PyDict_SetItem(dict, new BorrowedReference(key), value); + /// + /// Return 0 on success or -1 on failure. + /// + internal static int PyDict_SetItem(BorrowedReference dict, BorrowedReference key, BorrowedReference value) => Delegates.PyDict_SetItem(dict, key, 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); + internal static int PyDict_SetItemString(IntPtr dict, string key, IntPtr value) + => PyDict_SetItemString(new BorrowedReference(dict), key, new BorrowedReference(value)); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_DelItem(IntPtr pointer, IntPtr key); + /// + /// Return 0 on success or -1 on failure. + /// + internal static int PyDict_SetItemString(BorrowedReference dict, string key, BorrowedReference value) + { + using var keyPtr = new StrPtr(key, Encoding.UTF8); + return Delegates.PyDict_SetItemString(dict, keyPtr, value); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_DelItemString(IntPtr pointer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string key); + internal static int PyDict_DelItem(BorrowedReference pointer, BorrowedReference key) => Delegates.PyDict_DelItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyMapping_HasKey(IntPtr pointer, IntPtr key); + + internal static int PyDict_DelItemString(BorrowedReference pointer, string key) + { + using var keyPtr = new StrPtr(key, Encoding.UTF8); + return Delegates.PyDict_DelItemString(pointer, keyPtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Keys(IntPtr pointer); + internal static int PyMapping_HasKey(IntPtr pointer, IntPtr key) => Delegates.PyMapping_HasKey(pointer, key); - [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); + [Obsolete] + internal static IntPtr PyDict_Keys(IntPtr pointer) + => Delegates.PyDict_Keys(new BorrowedReference(pointer)) + .DangerousMoveToPointerOrNull(); + internal static NewReference PyDict_Keys(BorrowedReference pointer) => Delegates.PyDict_Keys(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Copy(IntPtr pointer); + + internal static IntPtr PyDict_Values(IntPtr pointer) => Delegates.PyDict_Values(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_Update(IntPtr pointer, IntPtr other); + + internal static NewReference PyDict_Items(BorrowedReference pointer) => Delegates.PyDict_Items(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyDict_Clear(IntPtr pointer); + + internal static IntPtr PyDict_Copy(IntPtr pointer) => Delegates.PyDict_Copy(pointer); + + + internal static int PyDict_Update(BorrowedReference pointer, BorrowedReference other) => Delegates.PyDict_Update(pointer, other); + + + internal static void PyDict_Clear(IntPtr pointer) => Delegates.PyDict_Clear(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); + + internal static IntPtr _PyDict_Size(IntPtr pointer) => Delegates._PyDict_Size(pointer); - /// - /// Return value: New reference. - /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PySet_New(IntPtr iterable); + internal static NewReference PySet_New(BorrowedReference iterable) => Delegates.PySet_New(iterable); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PySet_Add(IntPtr set, IntPtr key); + + internal static int PySet_Add(BorrowedReference set, BorrowedReference key) => Delegates.PySet_Add(set, 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); + + internal static int PySet_Contains(BorrowedReference anyset, BorrowedReference key) => Delegates.PySet_Contains(anyset, key); //==================================================================== // Python list API @@ -1724,73 +1759,72 @@ 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); + + private static IntPtr PyList_New(IntPtr size) => Delegates.PyList_New(size); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyList_AsTuple(IntPtr pointer); + + internal static IntPtr PyList_AsTuple(IntPtr pointer) => Delegates.PyList_AsTuple(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); + + private static BorrowedReference PyList_GetItem(BorrowedReference pointer, IntPtr index) => Delegates.PyList_GetItem(pointer, 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); + + private static int PyList_SetItem(IntPtr pointer, IntPtr index, IntPtr value) => Delegates.PyList_SetItem(pointer, index, 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); + + private static int PyList_Insert(BorrowedReference pointer, IntPtr index, IntPtr value) => Delegates.PyList_Insert(pointer, index, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Append(BorrowedReference pointer, IntPtr value); + + internal static int PyList_Append(BorrowedReference pointer, IntPtr value) => Delegates.PyList_Append(pointer, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Reverse(BorrowedReference pointer); + + internal static int PyList_Reverse(BorrowedReference pointer) => Delegates.PyList_Reverse(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Sort(BorrowedReference pointer); + + internal static int PyList_Sort(BorrowedReference pointer) => Delegates.PyList_Sort(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); + + private static IntPtr PyList_GetSlice(IntPtr pointer, IntPtr start, IntPtr end) => Delegates.PyList_GetSlice(pointer, start, 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); - } + + private static int PyList_SetSlice(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value) => Delegates.PyList_SetSlice(pointer, start, end, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")] - private static extern IntPtr _PyList_Size(BorrowedReference pointer); + + internal static nint PyList_Size(BorrowedReference pointer) => Delegates.PyList_Size(pointer); //==================================================================== // Python tuple API //==================================================================== + internal static bool PyTuple_Check(BorrowedReference ob) + { + return PyObject_TYPE(ob) == new BorrowedReference(PyTupleType); + } internal static bool PyTuple_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyTupleType; @@ -1801,44 +1835,39 @@ 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); + + private static IntPtr PyTuple_New(IntPtr size) => Delegates.PyTuple_New(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)); + return PyTuple_GetItem(new BorrowedReference(pointer), new IntPtr(index)) + .DangerousGetAddressOrNull(); } - [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); + + private static BorrowedReference PyTuple_GetItem(BorrowedReference pointer, IntPtr index) => Delegates.PyTuple_GetItem(pointer, 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); + + private static int PyTuple_SetItem(IntPtr pointer, IntPtr index, IntPtr value) => Delegates.PyTuple_SetItem(pointer, index, 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); + + private static IntPtr PyTuple_GetSlice(IntPtr pointer, IntPtr start, IntPtr end) => Delegates.PyTuple_GetSlice(pointer, start, 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); + internal static nint PyTuple_Size(IntPtr pointer) => PyTuple_Size(new BorrowedReference(pointer)); + internal static nint PyTuple_Size(BorrowedReference pointer) => Delegates.PyTuple_Size(pointer); //==================================================================== @@ -1852,87 +1881,109 @@ internal static bool PyIter_Check(IntPtr pointer) 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); + + internal static IntPtr PyIter_Next(IntPtr pointer) + => Delegates.PyIter_Next(new BorrowedReference(pointer)).DangerousMoveToPointerOrNull(); + internal static NewReference PyIter_Next(BorrowedReference pointer) => Delegates.PyIter_Next(pointer); //==================================================================== // Python module API //==================================================================== - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyModule_New(string name); + + internal static NewReference PyModule_New(string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyModule_New(namePtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern string PyModule_GetName(IntPtr module); + internal static string PyModule_GetName(IntPtr module) + => Delegates.PyModule_GetName(module).ToString(Encoding.UTF8); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyModule_GetDict(IntPtr module); + internal static BorrowedReference PyModule_GetDict(BorrowedReference module) => Delegates.PyModule_GetDict(module); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern string PyModule_GetFilename(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 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] + #endif - internal static extern IntPtr PyModule_Create2(IntPtr module, int apiver); + internal static IntPtr PyModule_Create2(IntPtr module, int apiver) => Delegates.PyModule_Create2(module, apiver); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_Import(IntPtr name); + + internal static IntPtr PyImport_Import(IntPtr name) => Delegates.PyImport_Import(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); + internal static IntPtr PyImport_ImportModule(string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyImport_ImportModule(namePtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_AddModule(string name); + internal static IntPtr PyImport_ReloadModule(IntPtr module) => Delegates.PyImport_ReloadModule(module); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_GetModuleDict(); + + internal static BorrowedReference PyImport_AddModule(string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PyImport_AddModule(namePtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PySys_SetArgvEx( - int argc, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, - int updatepath - ); + internal static BorrowedReference PyImport_GetModuleDict() => Delegates.PyImport_GetModuleDict(); + + + internal static void PySys_SetArgvEx(int argc, string[] argv, int updatepath) + { + var marshaler = StrArrayMarshaler.GetInstance(null); + var argvPtr = marshaler.MarshalManagedToNative(argv); + try + { + Delegates.PySys_SetArgvEx(argc, argvPtr, updatepath); + } + finally + { + marshaler.CleanUpNativeData(argvPtr); + } + } /// /// 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); + internal static BorrowedReference PySys_GetObject(string name) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PySys_GetObject(namePtr); + } + + internal static int PySys_SetObject(string name, BorrowedReference ob) + { + using var namePtr = new StrPtr(name, Encoding.UTF8); + return Delegates.PySys_SetObject(namePtr, 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 void PyType_Modified(IntPtr type) => Delegates.PyType_Modified(type); + internal static bool PyType_IsSubtype(BorrowedReference t1, IntPtr ofType) + => PyType_IsSubtype(t1, new BorrowedReference(ofType)); + internal static bool PyType_IsSubtype(BorrowedReference t1, BorrowedReference t2) => Delegates.PyType_IsSubtype(t1, t2); internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) => PyObject_TypeCheck(new BorrowedReference(ob), new BorrowedReference(tp)); @@ -1942,54 +1993,53 @@ internal static bool PyObject_TypeCheck(BorrowedReference ob, BorrowedReference return (t == tp) || PyType_IsSubtype(t, tp); } - internal static bool PyType_IsSameAsOrSubtype(IntPtr type, IntPtr ofType) + internal static bool PyType_IsSameAsOrSubtype(BorrowedReference type, IntPtr ofType) + => PyType_IsSameAsOrSubtype(type, new BorrowedReference(ofType)); + internal static bool PyType_IsSameAsOrSubtype(BorrowedReference type, BorrowedReference ofType) { return (type == ofType) || PyType_IsSubtype(type, ofType); } - /// - /// Generic handler for the tp_new slot of a type object. Create a new instance using the type’s tp_alloc slot. - /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kwds); + + internal static IntPtr PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kw) => Delegates.PyType_GenericNew(type, args, 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); + + private static IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n) => Delegates.PyType_GenericAlloc(type, 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); + + internal static int PyType_Ready(IntPtr type) => Delegates.PyType_Ready(type); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr _PyType_Lookup(IntPtr type, IntPtr name); + + internal static IntPtr _PyType_Lookup(IntPtr type, IntPtr name) => Delegates._PyType_Lookup(type, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GenericGetAttr(IntPtr obj, IntPtr name); + + internal static IntPtr PyObject_GenericGetAttr(IntPtr obj, IntPtr name) => Delegates.PyObject_GenericGetAttr(obj, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value); + + internal static int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value) => Delegates.PyObject_GenericSetAttr(obj, name, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr _PyObject_GetDictPtr(IntPtr obj); + + internal static BorrowedReference* _PyObject_GetDictPtr(BorrowedReference obj) => Delegates._PyObject_GetDictPtr(obj); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyObject_GC_Del(IntPtr tp); + + internal static void PyObject_GC_Del(IntPtr tp) => Delegates.PyObject_GC_Del(tp); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyObject_GC_Track(IntPtr tp); + + internal static void PyObject_GC_Track(IntPtr tp) => Delegates.PyObject_GC_Track(tp); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyObject_GC_UnTrack(IntPtr tp); + + internal static void PyObject_GC_UnTrack(IntPtr tp) => Delegates.PyObject_GC_UnTrack(tp); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void _PyObject_Dump(IntPtr ob); + + internal static void _PyObject_Dump(IntPtr ob) => Delegates._PyObject_Dump(ob); //==================================================================== // Python memory API @@ -2000,84 +2050,79 @@ 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); + + private static IntPtr PyMem_Malloc(IntPtr size) => Delegates.PyMem_Malloc(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); + + private static IntPtr PyMem_Realloc(IntPtr ptr, IntPtr size) => Delegates.PyMem_Realloc(ptr, size); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyMem_Free(IntPtr ptr); + + internal static void PyMem_Free(IntPtr ptr) => Delegates.PyMem_Free(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); + + internal static void PyErr_SetString(IntPtr ob, string message) + { + using var msgPtr = new StrPtr(message, Encoding.UTF8); + Delegates.PyErr_SetString(ob, msgPtr); + } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_SetObject(BorrowedReference type, BorrowedReference exceptionObject); + internal static void PyErr_SetObject(BorrowedReference type, BorrowedReference exceptionObject) => Delegates.PyErr_SetObject(type, exceptionObject); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyErr_SetFromErrno(IntPtr ob); + + internal static IntPtr PyErr_SetFromErrno(IntPtr ob) => Delegates.PyErr_SetFromErrno(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_SetNone(IntPtr ob); + + internal static void PyErr_SetNone(IntPtr ob) => Delegates.PyErr_SetNone(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyErr_ExceptionMatches(IntPtr exception); + + internal static int PyErr_ExceptionMatches(IntPtr exception) => Delegates.PyErr_ExceptionMatches(exception); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val); + + internal static int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val) => Delegates.PyErr_GivenExceptionMatches(ob, val); - /// - /// Under certain circumstances, the values returned by PyErr_Fetch() below can be “unnormalized”, - /// meaning that *exc is a class object but *val is not an instance of the same class. - /// This function can be used to instantiate the class in that case. - /// If the values are already normalized, nothing happens. - /// The delayed normalization is implemented to improve performance. - /// Must not be called when an error is set. - /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_NormalizeException(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + + internal static void PyErr_NormalizeException(ref IntPtr ob, ref IntPtr val, ref IntPtr tb) => Delegates.PyErr_NormalizeException(ref ob, ref val, ref tb); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyErr_Occurred(); + + internal static IntPtr PyErr_Occurred() => Delegates.PyErr_Occurred(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb); + + internal static void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb) => Delegates.PyErr_Fetch(out ob, out val, out tb); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb); + + internal static void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_Restore(ob, val, tb); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_Clear(); + + internal static void PyErr_Clear() => Delegates.PyErr_Clear(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_Print(); + + internal static void PyErr_Print() => Delegates.PyErr_Print(); /// /// Set the cause associated with the exception to cause. Use NULL to clear it. There is no type check to make sure that cause is either an exception instance or None. This steals a reference to cause. /// - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyException_SetCause(IntPtr ex, IntPtr cause); + + internal static void PyException_SetCause(IntPtr ex, IntPtr cause) => Delegates.PyException_SetCause(ex, cause); //==================================================================== // 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); + internal static NewReference PyCell_Get(BorrowedReference cell) => Delegates.PyCell_Get(cell); + + + internal static int PyCell_Set(BorrowedReference cell, IntPtr value) => Delegates.PyCell_Set(cell, value); //==================================================================== // Python GC API @@ -2089,14 +2134,14 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) internal const long _PyGC_REFS_TENTATIVELY_UNREACHABLE = -4; - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyGC_Collect(); + + internal static IntPtr PyGC_Collect() => Delegates.PyGC_Collect(); - internal static IntPtr _Py_AS_GC(IntPtr ob) + internal static IntPtr _Py_AS_GC(BorrowedReference 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; + return ob.DangerousGetAddress() - (Is32Bit ? 16 : 24); } internal static IntPtr _Py_FROM_GC(IntPtr gc) @@ -2118,15 +2163,13 @@ internal static IntPtr _PyGCHead_REFS(IntPtr gc) } } - internal static IntPtr _PyGC_REFS(IntPtr ob) + internal static IntPtr _PyGC_REFS(BorrowedReference 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 bool _PyObject_GC_IS_TRACKED(BorrowedReference ob) + => (long)_PyGC_REFS(ob) != _PyGC_REFS_UNTRACKED; internal static void Py_CLEAR(ref IntPtr ob) { @@ -2138,36 +2181,37 @@ internal static void Py_CLEAR(ref IntPtr ob) // 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); + internal static NewReference PyCapsule_New(IntPtr pointer, IntPtr name, IntPtr destructor) + => Delegates.PyCapsule_New(pointer, name, destructor); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyCapsule_SetPointer(BorrowedReference capsule, IntPtr pointer); + internal static IntPtr PyCapsule_GetPointer(BorrowedReference capsule, IntPtr name) + { + return Delegates.PyCapsule_GetPointer(capsule, name); + } + + internal static int PyCapsule_SetPointer(BorrowedReference capsule, IntPtr pointer) => Delegates.PyCapsule_SetPointer(capsule, pointer); //==================================================================== // Miscellaneous //==================================================================== - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyMethod_Self(IntPtr ob); + + internal static IntPtr PyMethod_Self(IntPtr ob) => Delegates.PyMethod_Self(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyMethod_Function(IntPtr ob); + + internal static IntPtr PyMethod_Function(IntPtr ob) => Delegates.PyMethod_Function(ob); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int Py_AddPendingCall(IntPtr func, IntPtr arg); + + internal static int Py_AddPendingCall(IntPtr func, IntPtr arg) => Delegates.Py_AddPendingCall(func, arg); - [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExcLLP64(uint id, IntPtr exc); + + internal static int PyThreadState_SetAsyncExcLLP64(uint id, IntPtr exc) => Delegates.PyThreadState_SetAsyncExcLLP64(id, exc); + + internal static int PyThreadState_SetAsyncExcLP64(ulong id, IntPtr exc) => Delegates.PyThreadState_SetAsyncExcLP64(id, exc); - [DllImport(_PythonDll, EntryPoint = "PyThreadState_SetAsyncExc", CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyThreadState_SetAsyncExcLP64(ulong id, IntPtr exc); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int Py_MakePendingCalls(); + internal static int Py_MakePendingCalls() => Delegates.Py_MakePendingCalls(); internal static void SetNoSiteFlag() { @@ -2202,6 +2246,540 @@ internal static IntPtr GetBuiltins() { return PyImport_Import(PyIdentifier.builtins); } + + private static class Delegates + { + static readonly ILibraryLoader libraryLoader = LibraryLoader.Instance; + + static Delegates() + { + PyDictProxy_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(_PythonDll)); + Py_IncRef = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(_PythonDll)); + Py_DecRef = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(_PythonDll)); + Py_Initialize = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(_PythonDll)); + Py_InitializeEx = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(_PythonDll)); + Py_IsInitialized = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(_PythonDll)); + Py_Finalize = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(_PythonDll)); + Py_NewInterpreter = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(_PythonDll)); + Py_EndInterpreter = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(_PythonDll)); + PyThreadState_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(_PythonDll)); + PyThreadState_Get = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(_PythonDll)); + _PyThreadState_UncheckedGet = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyThreadState_UncheckedGet), GetUnmanagedDll(_PythonDll)); + PyThread_get_key_value = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(_PythonDll)); + PyThread_get_thread_ident = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(_PythonDll)); + PyThread_set_key_value = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(_PythonDll)); + PyThreadState_Swap = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(_PythonDll)); + PyGILState_Ensure = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(_PythonDll)); + PyGILState_Release = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(_PythonDll)); + PyGILState_GetThisThreadState = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(_PythonDll)); + Py_Main = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(_PythonDll)); + PyEval_InitThreads = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(_PythonDll)); + PyEval_ThreadsInitialized = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(_PythonDll)); + PyEval_AcquireLock = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(_PythonDll)); + PyEval_ReleaseLock = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(_PythonDll)); + PyEval_AcquireThread = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(_PythonDll)); + PyEval_ReleaseThread = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(_PythonDll)); + PyEval_SaveThread = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(_PythonDll)); + PyEval_RestoreThread = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(_PythonDll)); + PyEval_GetBuiltins = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(_PythonDll)); + PyEval_GetGlobals = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(_PythonDll)); + PyEval_GetLocals = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(_PythonDll)); + Py_GetProgramName = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(_PythonDll)); + Py_SetProgramName = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(_PythonDll)); + Py_GetPythonHome = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(_PythonDll)); + Py_SetPythonHome = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(_PythonDll)); + Py_GetPath = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(_PythonDll)); + Py_SetPath = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(_PythonDll)); + Py_GetVersion = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(_PythonDll)); + Py_GetPlatform = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(_PythonDll)); + Py_GetCopyright = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(_PythonDll)); + Py_GetCompiler = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(_PythonDll)); + Py_GetBuildInfo = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(_PythonDll)); + PyRun_SimpleStringFlags = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyRun_SimpleStringFlags), GetUnmanagedDll(_PythonDll)); + PyRun_StringFlags = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyRun_StringFlags), GetUnmanagedDll(_PythonDll)); + PyEval_EvalCode = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(_PythonDll)); + Py_CompileStringObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_CompileStringObject), GetUnmanagedDll(_PythonDll)); + PyImport_ExecCodeModule = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(_PythonDll)); + PyCFunction_NewEx = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(_PythonDll)); + PyCFunction_Call = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(_PythonDll)); + PyMethod_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMethod_New), GetUnmanagedDll(_PythonDll)); + PyObject_HasAttrString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(_PythonDll)); + PyObject_GetAttrString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(_PythonDll)); + PyObject_SetAttrString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(_PythonDll)); + PyObject_HasAttr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(_PythonDll)); + PyObject_GetAttr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(_PythonDll)); + PyObject_SetAttr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(_PythonDll)); + PyObject_GetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(_PythonDll)); + PyObject_SetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(_PythonDll)); + PyObject_DelItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(_PythonDll)); + PyObject_GetIter = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(_PythonDll)); + PyObject_Call = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(_PythonDll)); + PyObject_CallObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(_PythonDll)); + PyObject_RichCompareBool = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(_PythonDll)); + PyObject_IsInstance = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(_PythonDll)); + PyObject_IsSubclass = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(_PythonDll)); + PyCallable_Check = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(_PythonDll)); + PyObject_IsTrue = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(_PythonDll)); + PyObject_Not = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(_PythonDll)); + _PyObject_Size = (delegate* unmanaged[Cdecl])GetFunctionByName("PyObject_Size", GetUnmanagedDll(_PythonDll)); + 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_Unicode = (delegate* unmanaged[Cdecl])GetFunctionByName("PyObject_Str", 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)); + try + { + PyBuffer_SizeFromFormat = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_SizeFromFormat), GetUnmanagedDll(_PythonDll)); + } + catch (MissingMethodException) + { + // only in 3.9+ + } + PyBuffer_IsContiguous = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_IsContiguous), GetUnmanagedDll(_PythonDll)); + PyBuffer_GetPointer = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_GetPointer), GetUnmanagedDll(_PythonDll)); + PyBuffer_FromContiguous = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_FromContiguous), GetUnmanagedDll(_PythonDll)); + PyBuffer_ToContiguous = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_ToContiguous), GetUnmanagedDll(_PythonDll)); + PyBuffer_FillContiguousStrides = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_FillContiguousStrides), GetUnmanagedDll(_PythonDll)); + PyBuffer_FillInfo = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBuffer_FillInfo), GetUnmanagedDll(_PythonDll)); + PyNumber_Int = (delegate* unmanaged[Cdecl])GetFunctionByName("PyNumber_Long", GetUnmanagedDll(_PythonDll)); + PyNumber_Long = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(_PythonDll)); + PyNumber_Float = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(_PythonDll)); + PyNumber_Check = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(_PythonDll)); + PyInt_FromLong = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(_PythonDll)); + PyInt_AsLong = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(_PythonDll)); + PyLong_FromLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(_PythonDll)); + PyLong_FromUnsignedLong32 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_FromUnsignedLong", GetUnmanagedDll(_PythonDll)); + PyLong_FromUnsignedLong64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_FromUnsignedLong", GetUnmanagedDll(_PythonDll)); + PyLong_FromDouble = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(_PythonDll)); + PyLong_FromLongLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(_PythonDll)); + PyLong_FromUnsignedLongLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(_PythonDll)); + PyLong_FromString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(_PythonDll)); + PyLong_AsLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(_PythonDll)); + PyLong_AsUnsignedLong32 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsUnsignedLong", GetUnmanagedDll(_PythonDll)); + PyLong_AsUnsignedLong64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsUnsignedLong", GetUnmanagedDll(_PythonDll)); + PyLong_AsLongLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(_PythonDll)); + PyLong_AsUnsignedLongLong = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(_PythonDll)); + PyLong_FromVoidPtr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_FromVoidPtr), GetUnmanagedDll(_PythonDll)); + PyLong_AsVoidPtr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyLong_AsVoidPtr), GetUnmanagedDll(_PythonDll)); + PyFloat_FromDouble = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(_PythonDll)); + PyFloat_FromString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(_PythonDll)); + PyFloat_AsDouble = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(_PythonDll)); + PyNumber_Add = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(_PythonDll)); + PyNumber_Subtract = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(_PythonDll)); + PyNumber_Multiply = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(_PythonDll)); + PyNumber_TrueDivide = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_TrueDivide), GetUnmanagedDll(_PythonDll)); + PyNumber_And = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(_PythonDll)); + PyNumber_Xor = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(_PythonDll)); + PyNumber_Or = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(_PythonDll)); + PyNumber_Lshift = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(_PythonDll)); + PyNumber_Rshift = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(_PythonDll)); + PyNumber_Power = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(_PythonDll)); + PyNumber_Remainder = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceAdd = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceSubtract = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceMultiply = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceTrueDivide = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceTrueDivide), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceAnd = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceXor = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceOr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceLshift = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceRshift = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlacePower = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(_PythonDll)); + PyNumber_InPlaceRemainder = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(_PythonDll)); + PyNumber_Negative = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(_PythonDll)); + PyNumber_Positive = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(_PythonDll)); + PyNumber_Invert = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(_PythonDll)); + PySequence_Check = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(_PythonDll)); + PySequence_GetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(_PythonDll)); + PySequence_SetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(_PythonDll)); + PySequence_DelItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(_PythonDll)); + PySequence_GetSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(_PythonDll)); + PySequence_SetSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(_PythonDll)); + PySequence_DelSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(_PythonDll)); + PySequence_Size = (delegate* unmanaged[Cdecl])GetFunctionByName("PySequence_Size", GetUnmanagedDll(_PythonDll)); + PySequence_Contains = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(_PythonDll)); + PySequence_Concat = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(_PythonDll)); + PySequence_Repeat = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(_PythonDll)); + PySequence_Index = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(_PythonDll)); + _PySequence_Count = (delegate* unmanaged[Cdecl])GetFunctionByName("PySequence_Count", GetUnmanagedDll(_PythonDll)); + PySequence_Tuple = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(_PythonDll)); + PySequence_List = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(_PythonDll)); + PyBytes_FromString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(_PythonDll)); + _PyBytes_Size = (delegate* unmanaged[Cdecl])GetFunctionByName("PyBytes_Size", GetUnmanagedDll(_PythonDll)); + PyUnicode_FromStringAndSize = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(_PythonDll)); + PyUnicode_AsUTF8 = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_AsUTF8), GetUnmanagedDll(_PythonDll)); + PyUnicode_FromObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(_PythonDll)); + PyUnicode_FromEncodedObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(_PythonDll)); + PyUnicode_FromKindAndData = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(_PythonDll)); + PyUnicode_GetMax = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_GetMax), GetUnmanagedDll(_PythonDll)); + _PyUnicode_GetSize = (delegate* unmanaged[Cdecl])GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(_PythonDll)); + PyUnicode_AsUnicode = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(_PythonDll)); + PyUnicode_AsUTF16String = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_AsUTF16String), GetUnmanagedDll(_PythonDll)); + PyUnicode_FromOrdinal = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(_PythonDll)); + PyUnicode_InternFromString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_InternFromString), GetUnmanagedDll(_PythonDll)); + PyUnicode_Compare = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyUnicode_Compare), GetUnmanagedDll(_PythonDll)); + PyDict_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(_PythonDll)); + PyDict_Next = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Next), GetUnmanagedDll(_PythonDll)); + PyDict_GetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(_PythonDll)); + PyDict_GetItemString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(_PythonDll)); + PyDict_SetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(_PythonDll)); + PyDict_SetItemString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(_PythonDll)); + PyDict_DelItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(_PythonDll)); + PyDict_DelItemString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(_PythonDll)); + PyMapping_HasKey = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(_PythonDll)); + PyDict_Keys = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(_PythonDll)); + PyDict_Values = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(_PythonDll)); + PyDict_Items = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(_PythonDll)); + PyDict_Copy = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(_PythonDll)); + PyDict_Update = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(_PythonDll)); + PyDict_Clear = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(_PythonDll)); + _PyDict_Size = (delegate* unmanaged[Cdecl])GetFunctionByName("PyDict_Size", GetUnmanagedDll(_PythonDll)); + PySet_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySet_New), GetUnmanagedDll(_PythonDll)); + PySet_Add = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySet_Add), GetUnmanagedDll(_PythonDll)); + PySet_Contains = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySet_Contains), GetUnmanagedDll(_PythonDll)); + PyList_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(_PythonDll)); + PyList_AsTuple = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(_PythonDll)); + PyList_GetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(_PythonDll)); + PyList_SetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(_PythonDll)); + PyList_Insert = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(_PythonDll)); + PyList_Append = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(_PythonDll)); + PyList_Reverse = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(_PythonDll)); + PyList_Sort = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(_PythonDll)); + PyList_GetSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(_PythonDll)); + PyList_SetSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(_PythonDll)); + PyList_Size = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyList_Size), GetUnmanagedDll(_PythonDll)); + PyTuple_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(_PythonDll)); + PyTuple_GetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(_PythonDll)); + PyTuple_SetItem = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(_PythonDll)); + PyTuple_GetSlice = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(_PythonDll)); + PyTuple_Size = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyTuple_Size), GetUnmanagedDll(_PythonDll)); + PyIter_Next = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(_PythonDll)); + PyModule_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(_PythonDll)); + 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)); + 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)); + PyImport_AddModule = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(_PythonDll)); + PyImport_GetModuleDict = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(_PythonDll)); + PySys_SetArgvEx = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(_PythonDll)); + PySys_GetObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(_PythonDll)); + PySys_SetObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(_PythonDll)); + PyType_Modified = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(_PythonDll)); + PyType_IsSubtype = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(_PythonDll)); + PyType_GenericNew = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(_PythonDll)); + PyType_GenericAlloc = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(_PythonDll)); + PyType_Ready = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(_PythonDll)); + _PyType_Lookup = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(_PythonDll)); + PyObject_GenericGetAttr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(_PythonDll)); + PyObject_GenericSetAttr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(_PythonDll)); + _PyObject_GetDictPtr = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(_PythonDll)); + PyObject_GC_Del = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(_PythonDll)); + PyObject_GC_Track = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll)); + PyObject_GC_UnTrack = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll)); + _PyObject_Dump = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(_PyObject_Dump), GetUnmanagedDll(_PythonDll)); + PyMem_Malloc = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(_PythonDll)); + PyMem_Realloc = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(_PythonDll)); + PyMem_Free = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(_PythonDll)); + PyErr_SetString = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(_PythonDll)); + PyErr_SetObject = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(_PythonDll)); + PyErr_SetFromErrno = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(_PythonDll)); + PyErr_SetNone = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(_PythonDll)); + PyErr_ExceptionMatches = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(_PythonDll)); + PyErr_GivenExceptionMatches = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(_PythonDll)); + PyErr_NormalizeException = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(_PythonDll)); + PyErr_Occurred = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(_PythonDll)); + PyErr_Fetch = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(_PythonDll)); + PyErr_Restore = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(_PythonDll)); + PyErr_Clear = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(_PythonDll)); + PyErr_Print = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(_PythonDll)); + PyCell_Get = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCell_Get), GetUnmanagedDll(_PythonDll)); + PyCell_Set = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCell_Set), GetUnmanagedDll(_PythonDll)); + PyGC_Collect = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyGC_Collect), GetUnmanagedDll(_PythonDll)); + PyCapsule_New = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCapsule_New), GetUnmanagedDll(_PythonDll)); + PyCapsule_GetPointer = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCapsule_GetPointer), GetUnmanagedDll(_PythonDll)); + PyCapsule_SetPointer = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyCapsule_SetPointer), GetUnmanagedDll(_PythonDll)); + PyMethod_Self = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(_PythonDll)); + PyMethod_Function = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(_PythonDll)); + Py_AddPendingCall = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_AddPendingCall), GetUnmanagedDll(_PythonDll)); + Py_MakePendingCalls = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(Py_MakePendingCalls), GetUnmanagedDll(_PythonDll)); + PyLong_AsUnsignedSize_t = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsSize_t", GetUnmanagedDll(_PythonDll)); + PyLong_AsSignedSize_t = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsSsize_t", GetUnmanagedDll(_PythonDll)); + PyExplicitlyConvertToInt64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyLong_AsLongLong", GetUnmanagedDll(_PythonDll)); + PyDict_GetItemWithError = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyDict_GetItemWithError), GetUnmanagedDll(_PythonDll)); + PyException_SetCause = (delegate* unmanaged[Cdecl])GetFunctionByName(nameof(PyException_SetCause), GetUnmanagedDll(_PythonDll)); + PyThreadState_SetAsyncExcLLP64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyThreadState_SetAsyncExc", GetUnmanagedDll(_PythonDll)); + PyThreadState_SetAsyncExcLP64 = (delegate* unmanaged[Cdecl])GetFunctionByName("PyThreadState_SetAsyncExc", GetUnmanagedDll(_PythonDll)); + } + + static global::System.IntPtr GetUnmanagedDll(string libraryName) + { + if (libraryName is null) return IntPtr.Zero; + return libraryLoader.Load(libraryName); + } + + static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) + => libraryLoader.GetFunction(libraryHandle, functionName); + + internal static delegate* unmanaged[Cdecl] PyDictProxy_New { get; } + internal static delegate* unmanaged[Cdecl] Py_IncRef { get; } + internal static delegate* unmanaged[Cdecl] Py_DecRef { get; } + internal static delegate* unmanaged[Cdecl] Py_Initialize { get; } + internal static delegate* unmanaged[Cdecl] Py_InitializeEx { get; } + internal static delegate* unmanaged[Cdecl] Py_IsInitialized { get; } + internal static delegate* unmanaged[Cdecl] Py_Finalize { get; } + internal static delegate* unmanaged[Cdecl] Py_NewInterpreter { get; } + internal static delegate* unmanaged[Cdecl] Py_EndInterpreter { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_New { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_Get { get; } + internal static delegate* unmanaged[Cdecl] _PyThreadState_UncheckedGet { get; } + internal static delegate* unmanaged[Cdecl] PyThread_get_key_value { get; } + internal static delegate* unmanaged[Cdecl] PyThread_get_thread_ident { get; } + internal static delegate* unmanaged[Cdecl] PyThread_set_key_value { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_Swap { get; } + internal static delegate* unmanaged[Cdecl] PyGILState_Ensure { get; } + internal static delegate* unmanaged[Cdecl] PyGILState_Release { get; } + internal static delegate* unmanaged[Cdecl] PyGILState_GetThisThreadState { get; } + internal static delegate* unmanaged[Cdecl] Py_Main { get; } + internal static delegate* unmanaged[Cdecl] PyEval_InitThreads { get; } + internal static delegate* unmanaged[Cdecl] PyEval_ThreadsInitialized { get; } + internal static delegate* unmanaged[Cdecl] PyEval_AcquireLock { get; } + internal static delegate* unmanaged[Cdecl] PyEval_ReleaseLock { get; } + internal static delegate* unmanaged[Cdecl] PyEval_AcquireThread { get; } + internal static delegate* unmanaged[Cdecl] PyEval_ReleaseThread { get; } + internal static delegate* unmanaged[Cdecl] PyEval_SaveThread { get; } + internal static delegate* unmanaged[Cdecl] PyEval_RestoreThread { get; } + internal static delegate* unmanaged[Cdecl] PyEval_GetBuiltins { get; } + internal static delegate* unmanaged[Cdecl] PyEval_GetGlobals { get; } + internal static delegate* unmanaged[Cdecl] PyEval_GetLocals { get; } + internal static delegate* unmanaged[Cdecl] Py_GetProgramName { get; } + internal static delegate* unmanaged[Cdecl] Py_SetProgramName { get; } + internal static delegate* unmanaged[Cdecl] Py_GetPythonHome { get; } + internal static delegate* unmanaged[Cdecl] Py_SetPythonHome { get; } + internal static delegate* unmanaged[Cdecl] Py_GetPath { get; } + internal static delegate* unmanaged[Cdecl] Py_SetPath { get; } + internal static delegate* unmanaged[Cdecl] Py_GetVersion { get; } + internal static delegate* unmanaged[Cdecl] Py_GetPlatform { get; } + internal static delegate* unmanaged[Cdecl] Py_GetCopyright { get; } + internal static delegate* unmanaged[Cdecl] Py_GetCompiler { get; } + internal static delegate* unmanaged[Cdecl] Py_GetBuildInfo { get; } + internal static delegate* unmanaged[Cdecl] PyRun_SimpleStringFlags { get; } + internal static delegate* unmanaged[Cdecl] PyRun_StringFlags { get; } + internal static delegate* unmanaged[Cdecl] PyEval_EvalCode { get; } + internal static delegate* unmanaged[Cdecl] Py_CompileStringObject { get; } + internal static delegate* unmanaged[Cdecl] PyImport_ExecCodeModule { get; } + internal static delegate* unmanaged[Cdecl] PyCFunction_NewEx { get; } + internal static delegate* unmanaged[Cdecl] PyCFunction_Call { get; } + internal static delegate* unmanaged[Cdecl] PyMethod_New { get; } + internal static delegate* unmanaged[Cdecl] PyObject_HasAttrString { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GetAttrString { get; } + internal static delegate* unmanaged[Cdecl] PyObject_SetAttrString { get; } + internal static delegate* unmanaged[Cdecl] PyObject_HasAttr { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GetAttr { get; } + internal static delegate* unmanaged[Cdecl] PyObject_SetAttr { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GetItem { get; } + internal static delegate* unmanaged[Cdecl] PyObject_SetItem { get; } + internal static delegate* unmanaged[Cdecl] PyObject_DelItem { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GetIter { get; } + internal static delegate* unmanaged[Cdecl] PyObject_Call { get; } + internal static delegate* unmanaged[Cdecl] PyObject_CallObject { get; } + internal static delegate* unmanaged[Cdecl] PyObject_RichCompareBool { get; } + internal static delegate* unmanaged[Cdecl] PyObject_IsInstance { get; } + internal static delegate* unmanaged[Cdecl] PyObject_IsSubclass { get; } + internal static delegate* unmanaged[Cdecl] PyCallable_Check { get; } + internal static delegate* unmanaged[Cdecl] PyObject_IsTrue { get; } + internal static delegate* unmanaged[Cdecl] PyObject_Not { get; } + internal static delegate* unmanaged[Cdecl] _PyObject_Size { get; } + 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_Unicode { 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; } + internal static delegate* unmanaged[Cdecl] PyBuffer_SizeFromFormat { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_IsContiguous { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_GetPointer { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_FromContiguous { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_ToContiguous { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_FillContiguousStrides { get; } + internal static delegate* unmanaged[Cdecl] PyBuffer_FillInfo { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Int { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Long { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Float { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Check { get; } + internal static delegate* unmanaged[Cdecl] PyInt_FromLong { get; } + internal static delegate* unmanaged[Cdecl] PyInt_AsLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromUnsignedLong32 { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromUnsignedLong64 { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromDouble { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromLongLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromUnsignedLongLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromString { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsUnsignedLong32 { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsUnsignedLong64 { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsLongLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsUnsignedLongLong { get; } + internal static delegate* unmanaged[Cdecl] PyLong_FromVoidPtr { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsVoidPtr { get; } + internal static delegate* unmanaged[Cdecl] PyFloat_FromDouble { get; } + internal static delegate* unmanaged[Cdecl] PyFloat_FromString { get; } + internal static delegate* unmanaged[Cdecl] PyFloat_AsDouble { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Add { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Subtract { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Multiply { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_TrueDivide { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_And { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Xor { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Or { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Lshift { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Rshift { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Power { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Remainder { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceAdd { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceSubtract { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceMultiply { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceTrueDivide { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceAnd { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceXor { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceOr { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceLshift { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceRshift { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlacePower { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_InPlaceRemainder { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Negative { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Positive { get; } + internal static delegate* unmanaged[Cdecl] PyNumber_Invert { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Check { get; } + internal static delegate* unmanaged[Cdecl] PySequence_GetItem { get; } + internal static delegate* unmanaged[Cdecl] PySequence_SetItem { get; } + internal static delegate* unmanaged[Cdecl] PySequence_DelItem { get; } + internal static delegate* unmanaged[Cdecl] PySequence_GetSlice { get; } + internal static delegate* unmanaged[Cdecl] PySequence_SetSlice { get; } + internal static delegate* unmanaged[Cdecl] PySequence_DelSlice { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Size { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Contains { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Concat { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Repeat { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Index { get; } + internal static delegate* unmanaged[Cdecl] _PySequence_Count { get; } + internal static delegate* unmanaged[Cdecl] PySequence_Tuple { get; } + internal static delegate* unmanaged[Cdecl] PySequence_List { get; } + internal static delegate* unmanaged[Cdecl] PyBytes_FromString { get; } + internal static delegate* unmanaged[Cdecl] _PyBytes_Size { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_FromStringAndSize { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_AsUTF8 { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_FromObject { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_FromEncodedObject { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_FromKindAndData { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_GetMax { get; } + internal static delegate* unmanaged[Cdecl] _PyUnicode_GetSize { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_AsUnicode { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_AsUTF16String { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_FromOrdinal { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_InternFromString { get; } + internal static delegate* unmanaged[Cdecl] PyUnicode_Compare { get; } + internal static delegate* unmanaged[Cdecl] PyDict_New { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Next { get; } + internal static delegate* unmanaged[Cdecl] PyDict_GetItem { get; } + internal static delegate* unmanaged[Cdecl] PyDict_GetItemString { get; } + internal static delegate* unmanaged[Cdecl] PyDict_SetItem { get; } + internal static delegate* unmanaged[Cdecl] PyDict_SetItemString { get; } + internal static delegate* unmanaged[Cdecl] PyDict_DelItem { get; } + internal static delegate* unmanaged[Cdecl] PyDict_DelItemString { get; } + internal static delegate* unmanaged[Cdecl] PyMapping_HasKey { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Keys { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Values { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Items { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Copy { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Update { get; } + internal static delegate* unmanaged[Cdecl] PyDict_Clear { get; } + internal static delegate* unmanaged[Cdecl] _PyDict_Size { get; } + internal static delegate* unmanaged[Cdecl] PySet_New { get; } + internal static delegate* unmanaged[Cdecl] PySet_Add { get; } + internal static delegate* unmanaged[Cdecl] PySet_Contains { get; } + internal static delegate* unmanaged[Cdecl] PyList_New { get; } + internal static delegate* unmanaged[Cdecl] PyList_AsTuple { get; } + internal static delegate* unmanaged[Cdecl] PyList_GetItem { get; } + internal static delegate* unmanaged[Cdecl] PyList_SetItem { get; } + internal static delegate* unmanaged[Cdecl] PyList_Insert { get; } + internal static delegate* unmanaged[Cdecl] PyList_Append { get; } + internal static delegate* unmanaged[Cdecl] PyList_Reverse { get; } + internal static delegate* unmanaged[Cdecl] PyList_Sort { get; } + internal static delegate* unmanaged[Cdecl] PyList_GetSlice { get; } + internal static delegate* unmanaged[Cdecl] PyList_SetSlice { get; } + internal static delegate* unmanaged[Cdecl] PyList_Size { get; } + internal static delegate* unmanaged[Cdecl] PyTuple_New { get; } + internal static delegate* unmanaged[Cdecl] PyTuple_GetItem { get; } + internal static delegate* unmanaged[Cdecl] PyTuple_SetItem { get; } + internal static delegate* unmanaged[Cdecl] PyTuple_GetSlice { get; } + internal static delegate* unmanaged[Cdecl] PyTuple_Size { get; } + internal static delegate* unmanaged[Cdecl] PyIter_Next { get; } + internal static delegate* unmanaged[Cdecl] PyModule_New { get; } + internal static delegate* unmanaged[Cdecl] PyModule_GetName { get; } + internal static delegate* unmanaged[Cdecl] PyModule_GetDict { get; } + internal static delegate* unmanaged[Cdecl] PyModule_GetFilename { get; } + internal static delegate* unmanaged[Cdecl] PyModule_Create2 { get; } + internal static delegate* unmanaged[Cdecl] PyImport_Import { get; } + internal static delegate* unmanaged[Cdecl] PyImport_ImportModule { get; } + internal static delegate* unmanaged[Cdecl] PyImport_ReloadModule { get; } + internal static delegate* unmanaged[Cdecl] PyImport_AddModule { get; } + internal static delegate* unmanaged[Cdecl] PyImport_GetModuleDict { get; } + internal static delegate* unmanaged[Cdecl] PySys_SetArgvEx { get; } + internal static delegate* unmanaged[Cdecl] PySys_GetObject { get; } + internal static delegate* unmanaged[Cdecl] PySys_SetObject { get; } + internal static delegate* unmanaged[Cdecl] PyType_Modified { get; } + internal static delegate* unmanaged[Cdecl] PyType_IsSubtype { get; } + internal static delegate* unmanaged[Cdecl] PyType_GenericNew { get; } + internal static delegate* unmanaged[Cdecl] PyType_GenericAlloc { get; } + internal static delegate* unmanaged[Cdecl] PyType_Ready { get; } + internal static delegate* unmanaged[Cdecl] _PyType_Lookup { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GenericGetAttr { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GenericSetAttr { get; } + internal static delegate* unmanaged[Cdecl] _PyObject_GetDictPtr { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GC_Del { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GC_Track { get; } + internal static delegate* unmanaged[Cdecl] PyObject_GC_UnTrack { get; } + internal static delegate* unmanaged[Cdecl] _PyObject_Dump { get; } + internal static delegate* unmanaged[Cdecl] PyMem_Malloc { get; } + internal static delegate* unmanaged[Cdecl] PyMem_Realloc { get; } + internal static delegate* unmanaged[Cdecl] PyMem_Free { get; } + internal static delegate* unmanaged[Cdecl] PyErr_SetString { get; } + internal static delegate* unmanaged[Cdecl] PyErr_SetObject { get; } + internal static delegate* unmanaged[Cdecl] PyErr_SetFromErrno { get; } + internal static delegate* unmanaged[Cdecl] PyErr_SetNone { get; } + internal static delegate* unmanaged[Cdecl] PyErr_ExceptionMatches { get; } + internal static delegate* unmanaged[Cdecl] PyErr_GivenExceptionMatches { get; } + internal static delegate* unmanaged[Cdecl] PyErr_NormalizeException { get; } + internal static delegate* unmanaged[Cdecl] PyErr_Occurred { get; } + internal static delegate* unmanaged[Cdecl] PyErr_Fetch { get; } + internal static delegate* unmanaged[Cdecl] PyErr_Restore { get; } + internal static delegate* unmanaged[Cdecl] PyErr_Clear { get; } + internal static delegate* unmanaged[Cdecl] PyErr_Print { get; } + internal static delegate* unmanaged[Cdecl] PyCell_Get { get; } + internal static delegate* unmanaged[Cdecl] PyCell_Set { get; } + internal static delegate* unmanaged[Cdecl] PyGC_Collect { get; } + internal static delegate* unmanaged[Cdecl] PyCapsule_New { get; } + internal static delegate* unmanaged[Cdecl] PyCapsule_GetPointer { get; } + internal static delegate* unmanaged[Cdecl] PyCapsule_SetPointer { get; } + internal static delegate* unmanaged[Cdecl] PyMethod_Self { get; } + internal static delegate* unmanaged[Cdecl] PyMethod_Function { get; } + internal static delegate* unmanaged[Cdecl] Py_AddPendingCall { get; } + internal static delegate* unmanaged[Cdecl] Py_MakePendingCalls { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsUnsignedSize_t { get; } + internal static delegate* unmanaged[Cdecl] PyLong_AsSignedSize_t { get; } + internal static delegate* unmanaged[Cdecl] PyExplicitlyConvertToInt64 { get; } + internal static delegate* unmanaged[Cdecl] PyDict_GetItemWithError { get; } + internal static delegate* unmanaged[Cdecl] PyException_SetCause { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_SetAsyncExcLLP64 { get; } + internal static delegate* unmanaged[Cdecl] PyThreadState_SetAsyncExcLP64 { get; } + } } diff --git a/src/runtime/runtime_data.cs b/src/runtime/runtime_data.cs index f45e76db4..0b3bf3017 100644 --- a/src/runtime/runtime_data.cs +++ b/src/runtime/runtime_data.cs @@ -39,7 +39,7 @@ static void ClearCLRData () BorrowedReference capsule = PySys_GetObject("clr_data"); if (!capsule.IsNull) { - IntPtr oldData = PyCapsule_GetPointer(capsule, null); + IntPtr oldData = PyCapsule_GetPointer(capsule, IntPtr.Zero); PyMem_Free(oldData); PyCapsule_SetPointer(capsule, IntPtr.Zero); } @@ -85,8 +85,9 @@ internal static void Stash() Marshal.Copy(data, 0, mem + IntPtr.Size, (int)ms.Length); ClearCLRData(); - NewReference capsule = PyCapsule_New(mem, null, IntPtr.Zero); - PySys_SetObject("clr_data", capsule.DangerousGetAddress()); + + NewReference capsule = PyCapsule_New(mem, IntPtr.Zero, IntPtr.Zero); + PySys_SetObject("clr_data", capsule); // Let the dictionary own the reference capsule.Dispose(); } @@ -110,7 +111,7 @@ private static void RestoreRuntimeDataImpl() { return; } - IntPtr mem = PyCapsule_GetPointer(capsule, null); + IntPtr mem = PyCapsule_GetPointer(capsule, IntPtr.Zero); int length = (int)Marshal.ReadIntPtr(mem); byte[] data = new byte[length]; Marshal.Copy(mem + IntPtr.Size, data, 0, length); @@ -143,7 +144,7 @@ public static bool HasStashData() public static void ClearStash() { - PySys_SetObject("clr_data", IntPtr.Zero); + PySys_SetObject("clr_data", default); } static bool CheckSerializable (object o) @@ -295,7 +296,9 @@ private static void RestoreRuntimeDataModules(RuntimeDataStorage storage) var pyMoudles = PyImport_GetModuleDict(); foreach (var item in modules) { - int res = PyDict_SetItem(pyMoudles, item.Key, item.Value); + var moduleName = new BorrowedReference(item.Key); + var module = new BorrowedReference(item.Value); + int res = PyDict_SetItem(pyMoudles, moduleName, module); PythonException.ThrowIfIsNotZero(res); XDecref(item.Key); XDecref(item.Value); diff --git a/src/runtime/runtime_state.cs b/src/runtime/runtime_state.cs index 69acbcd31..295219675 100644 --- a/src/runtime/runtime_state.cs +++ b/src/runtime/runtime_state.cs @@ -19,20 +19,20 @@ public static void Save() throw new Exception("Runtime State set already"); } - IntPtr objs = IntPtr.Zero; + NewReference objs = default; if (ShouldRestoreObjects) { - objs = PySet_New(IntPtr.Zero); - foreach (var obj in PyGCGetObjects()) + objs = PySet_New(default); + foreach (var objRaw in PyGCGetObjects()) { - AddObjPtrToSet(objs, obj); + AddObjPtrToSet(objs, new BorrowedReference(objRaw)); } } - var modules = PySet_New(IntPtr.Zero); + var modules = PySet_New(default); foreach (var name in GetModuleNames()) { - int res = PySet_Add(modules, name); + int res = PySet_Add(modules, new BorrowedReference(name)); PythonException.ThrowIfIsNotZero(res); } @@ -46,10 +46,9 @@ public static void Save() head->gc.gc_refs = IntPtr.Zero; } { - var pyDummyGC = PyLong_FromVoidPtr(dummyGCHead); + using var pyDummyGC = PyLong_FromVoidPtr(dummyGCHead); int res = PySys_SetObject("dummy_gc", pyDummyGC); PythonException.ThrowIfIsNotZero(res); - XDecref(pyDummyGC); try { @@ -58,7 +57,7 @@ public static void Save() } finally { - XDecref(modules); + modules.Dispose(); } if (ShouldRestoreObjects) @@ -71,7 +70,7 @@ public static void Save() } finally { - XDecref(objs); + objs.Dispose(); } } } @@ -79,8 +78,8 @@ public static void Save() public static void Restore() { - var dummyGCAddr = PySys_GetObject("dummy_gc").DangerousGetAddress(); - if (dummyGCAddr == IntPtr.Zero) + var dummyGCAddr = PySys_GetObject("dummy_gc"); + if (dummyGCAddr.IsNull) { throw new InvalidOperationException("Runtime state have not set"); } @@ -97,9 +96,10 @@ private static void ResotreModules(IntPtr dummyGC) var intialModules = PySys_GetObject("initial_modules"); Debug.Assert(!intialModules.IsNull); var modules = PyImport_GetModuleDict(); - foreach (var name in GetModuleNames()) + foreach (var nameRaw in GetModuleNames()) { - if (PySet_Contains(intialModules.DangerousGetAddress(), name) == 1) + var name = new BorrowedReference(nameRaw); + if (PySet_Contains(intialModules, name) == 1) { continue; } @@ -122,21 +122,15 @@ private static void RestoreObjects(IntPtr dummyGC) { throw new Exception("To prevent crash by _PyObject_GC_UNTRACK in Python internal, UseDummyGC should be enabled when using ResotreObjects"); } - IntPtr intialObjs = PySys_GetObject("initial_objs").DangerousGetAddress(); - Debug.Assert(intialObjs != IntPtr.Zero); - foreach (var obj in PyGCGetObjects()) + BorrowedReference intialObjs = PySys_GetObject("initial_objs"); + Debug.Assert(@intialObjs.IsNull); + foreach (var objRaw in PyGCGetObjects()) { - var p = PyLong_FromVoidPtr(obj); - try - { - if (PySet_Contains(intialObjs, p) == 1) - { - continue; - } - } - finally + using var p = PyLong_FromVoidPtr(objRaw); + var obj = new BorrowedReference(objRaw); + if (PySet_Contains(intialObjs, p) == 1) { - XDecref(p); + continue; } Debug.Assert(_PyObject_GC_IS_TRACKED(obj), "A GC object must be tracked"); ExchangeGCChain(obj, dummyGC); @@ -162,34 +156,28 @@ public static IEnumerable PyGCGetObjects() public static IEnumerable GetModuleNames() { var modules = PyImport_GetModuleDict(); - var names = PyDict_Keys(modules); - var length = PyList_Size(new BorrowedReference(names)); + using var names = PyDict_Keys(modules); + var length = PyList_Size(names); + var result = new IntPtr[length]; for (int i = 0; i < length; i++) { - var name = PyList_GetItem(new BorrowedReference(names), i); - yield return name.DangerousGetAddress(); + result[i] = PyList_GetItem(names, i).DangerousGetAddress(); } - XDecref(names); + return result; } - private static void AddObjPtrToSet(IntPtr set, IntPtr obj) + private static void AddObjPtrToSet(BorrowedReference set, BorrowedReference obj) { - var p = PyLong_FromVoidPtr(obj); - XIncref(obj); - try - { - int res = PySet_Add(set, p); - PythonException.ThrowIfIsNotZero(res); - } - finally - { - XDecref(p); - } + IntPtr objRaw = obj.DangerousGetAddress(); + using var p = PyLong_FromVoidPtr(objRaw); + XIncref(objRaw); + int res = PySet_Add(set, p); + PythonException.ThrowIfIsNotZero(res); } /// /// Exchange gc to a dummy gc prevent nullptr error in _PyObject_GC_UnTrack macro. /// - private static void ExchangeGCChain(IntPtr obj, IntPtr gc) + private static void ExchangeGCChain(BorrowedReference obj, IntPtr gc) { var head = _Py_AS_GC(obj); if ((long)_PyGCHead_REFS(head) == _PyGC_REFS_UNTRACKED) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 3e9e44a46..e0564b243 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -102,6 +102,7 @@ internal static void RestoreRuntimeData(RuntimeDataStorage storage) /// object. These Python type instances are used to implement internal /// descriptor and utility types like ModuleObject, PropertyObject, etc. /// + [Obsolete] internal static IntPtr GetTypeHandle(Type type) { // Note that these types are cached with a refcount of 1, so they @@ -117,6 +118,14 @@ internal static IntPtr GetTypeHandle(Type type) _slotsImpls.Add(type, type); return handle; } + /// + /// Given a managed Type derived from ExtensionType, get the handle to + /// a Python type object that delegates its implementation to the Type + /// object. These Python type instances are used to implement internal + /// descriptor and utility types like ModuleObject, PropertyObject, etc. + /// + internal static BorrowedReference GetTypeReference(Type type) + => new BorrowedReference(GetTypeHandle(type)); /// @@ -171,10 +180,10 @@ internal static IntPtr CreateType(Type impl) throw new PythonException(); } - IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); - IntPtr mod = Runtime.PyString_FromString("CLR"); + var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); + var mod = NewReference.DangerousFromPointer(Runtime.PyString_FromString("CLR")); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); - Runtime.XDecref(mod); + mod.Dispose(); InitMethods(type, impl); @@ -294,11 +303,11 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) throw new PythonException(); } - IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); + var dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); string mn = clrType.Namespace ?? ""; - IntPtr mod = Runtime.PyString_FromString(mn); + var mod = NewReference.DangerousFromPointer(Runtime.PyString_FromString(mn)); Runtime.PyDict_SetItem(dict, PyIdentifier.__module__, mod); - Runtime.XDecref(mod); + mod.Dispose(); // Hide the gchandle of the implementation in a magic type slot. GCHandle gc = impl.AllocGCHandle(); @@ -372,11 +381,11 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr // by default the class dict will have all the C# methods in it, but as this is a // derived class we want the python overrides in there instead if they exist. - IntPtr cls_dict = Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict); - ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, py_dict)); + var cls_dict = new BorrowedReference(Marshal.ReadIntPtr(py_type, TypeOffset.tp_dict)); + ThrowIfIsNotZero(Runtime.PyDict_Update(cls_dict, new BorrowedReference(py_dict))); Runtime.XIncref(py_type); // Update the __classcell__ if it exists - var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__")); + BorrowedReference cell = Runtime.PyDict_GetItemString(cls_dict, "__classcell__"); if (!cell.IsNull) { ThrowIfIsNotZero(Runtime.PyCell_Set(cell, py_type)); @@ -522,7 +531,7 @@ private static IntPtr AddCustomMetaMethod(string name, IntPtr type, IntPtr mdef, IntPtr mdefAddr = mdef; slotsHolder.AddDealloctor(() => { - IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); + var tp_dict = new BorrowedReference(Marshal.ReadIntPtr(type, TypeOffset.tp_dict)); if (Runtime.PyDict_DelItemString(tp_dict, name) != 0) { Runtime.PyErr_Print(); @@ -913,32 +922,23 @@ static class SlotHelper { public static IntPtr CreateObjectType() { - IntPtr globals = Runtime.PyDict_New(); + using var globals = NewReference.DangerousFromPointer(Runtime.PyDict_New()); if (Runtime.PyDict_SetItemString(globals, "__builtins__", Runtime.PyEval_GetBuiltins()) != 0) { - Runtime.XDecref(globals); + globals.Dispose(); throw new PythonException(); } const string code = "class A(object): pass"; - var resRef = Runtime.PyRun_String(code, RunFlagType.File, globals, globals); - IntPtr res = resRef.DangerousGetAddress(); - if (res == IntPtr.Zero) + using var resRef = Runtime.PyRun_String(code, RunFlagType.File, globals, globals); + if (resRef.IsNull()) { - try - { - throw new PythonException(); - } - finally - { - Runtime.XDecref(globals); - } + globals.Dispose(); + throw new PythonException(); } resRef.Dispose(); - IntPtr A = Runtime.PyDict_GetItemString(globals, "A"); - Debug.Assert(A != IntPtr.Zero); - Runtime.XIncref(A); - Runtime.XDecref(globals); - return A; + BorrowedReference A = Runtime.PyDict_GetItemString(globals, "A"); + Debug.Assert(!A.IsNull); + return new NewReference(A).DangerousMoveToPointer(); } } } diff --git a/src/tests/tests.pyproj b/src/tests/tests.pyproj index 4bdbc6b14..439bc856a 100644 --- a/src/tests/tests.pyproj +++ b/src/tests/tests.pyproj @@ -14,14 +14,8 @@ - - - - - - - - + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets