From 1a82f40ec6e4a20ee9e3932df16cb5d3e40dd09a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 21 Jan 2019 14:42:35 -0800 Subject: [PATCH 001/240] added a regression test for #795 --- src/embed_tests/TestCallbacks.cs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/embed_tests/TestCallbacks.cs diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs new file mode 100644 index 000000000..8dfcdeaa4 --- /dev/null +++ b/src/embed_tests/TestCallbacks.cs @@ -0,0 +1,31 @@ +using System; + +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + public class TestCallbacks { + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + // regression test for https://github.com/pythonnet/pythonnet/issues/795 + [Test] + public void TestReentry() { + int passed = 0; + var aFunctionThatCallsIntoPython = new Action(CallMe); + using (Py.GIL()) { + dynamic callWith42 = PythonEngine.Eval("lambda f: f(42)"); + callWith42(aFunctionThatCallsIntoPython.ToPython()); + } + Assert.AreEqual(expected: 42, actual: passed); + } + static void CallMe(int value) { PythonEngine.Eval("42"); } + } +} From 5ce130e78fa4126890ba9250cb2aaabc358742e3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 27 Jan 2019 23:56:21 -0800 Subject: [PATCH 002/240] added TestSimpleCallback, fixed TestReentry to pass --- src/embed_tests/TestCallbacks.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index 8dfcdeaa4..51d3f939d 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -1,4 +1,4 @@ -using System; +using System; using NUnit.Framework; using Python.Runtime; @@ -15,17 +15,31 @@ public void Dispose() { PythonEngine.Shutdown(); } + [Test] + public void TestSimpleCallback() { + int passed = 0; + var aFunctionThatCallsIntoPython = new Action(value => passed = value); + using (Py.GIL()) { + dynamic callWith42 = PythonEngine.Eval("lambda f: f(42)"); + callWith42(aFunctionThatCallsIntoPython.ToPython()); + } + Assert.AreEqual(expected: 42, actual: passed); + } + // regression test for https://github.com/pythonnet/pythonnet/issues/795 [Test] public void TestReentry() { int passed = 0; - var aFunctionThatCallsIntoPython = new Action(CallMe); + var aFunctionThatCallsIntoPython = new Action(value => { + using (Py.GIL()) { + passed = (int)(dynamic)PythonEngine.Eval("42"); + } + }); using (Py.GIL()) { dynamic callWith42 = PythonEngine.Eval("lambda f: f(42)"); callWith42(aFunctionThatCallsIntoPython.ToPython()); } Assert.AreEqual(expected: 42, actual: passed); } - static void CallMe(int value) { PythonEngine.Eval("42"); } } } From 5b29fa22091690e68ef8de843b6c6a691af199de Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 28 Jan 2019 00:06:45 -0800 Subject: [PATCH 003/240] + TestInstanceWrapping.SimpleOverloadResolution --- src/embed_tests/TestInstanceWrapping.cs | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/embed_tests/TestInstanceWrapping.cs diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs new file mode 100644 index 000000000..078bafd27 --- /dev/null +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -0,0 +1,43 @@ +using System; + +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + using System.Globalization; + + public class TestInstanceWrapping { + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + [Test] + public void SimpleOverloadResolution() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallMe(42)"); + callWithInt(o); + Assert.AreEqual(42, overloaded.Value); + + dynamic callWithStr = PythonEngine.Eval("lambda o: o.CallMe('43')"); + callWithStr(o); + Assert.AreEqual(43, overloaded.Value); + } + } + + class Overloaded + { + public int Value { get; set; } + public void CallMe(int arg) => this.Value = arg; + public void CallMe(string arg) => + this.Value = int.Parse(arg, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + } +} From aafc1f8030a6026b04f78383a5aba5d5643e02c9 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 28 Jan 2019 00:23:48 -0800 Subject: [PATCH 004/240] added more overload resolution tests --- src/embed_tests/TestInstanceWrapping.cs | 54 ++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 078bafd27..f2206710b 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -18,26 +18,68 @@ public void Dispose() { } [Test] - public void SimpleOverloadResolution() { + public void OverloadResolution_IntOrStr() { var overloaded = new Overloaded(); using (Py.GIL()) { var o = overloaded.ToPython(); - dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallMe(42)"); + + dynamic callWithInt = PythonEngine.Eval("lambda o: o.IntOrStr(42)"); callWithInt(o); Assert.AreEqual(42, overloaded.Value); - dynamic callWithStr = PythonEngine.Eval("lambda o: o.CallMe('43')"); + dynamic callWithStr = PythonEngine.Eval("lambda o: o.IntOrStr('43')"); callWithStr(o); Assert.AreEqual(43, overloaded.Value); } } - class Overloaded + [Test] + public void OverloadResolution_ObjOrClass() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithConcrete = PythonEngine.Eval("lambda o: o.ObjOrClass(o)"); + callWithConcrete(o); + Assert.AreEqual(Overloaded.ConcreteClass, overloaded.Value); + + dynamic callWithUnknown = PythonEngine.Eval("lambda o: o.ObjOrClass([])"); + callWithUnknown(o); + Assert.AreEqual(Overloaded.Object, overloaded.Value); + } + } + + [Test] + public void OverloadResolution_BaseOrDerived() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithSelf = PythonEngine.Eval("lambda o: o.BaseOrDerived(o)"); + callWithSelf(o); + Assert.AreEqual(Overloaded.Derived, overloaded.Value); + } + } + + class Base {} + class Derived: Base { } + + class Overloaded: Derived { public int Value { get; set; } - public void CallMe(int arg) => this.Value = arg; - public void CallMe(string arg) => + public void IntOrStr(int arg) => this.Value = arg; + public void IntOrStr(string arg) => this.Value = int.Parse(arg, NumberStyles.Integer, CultureInfo.InvariantCulture); + + public const int Object = 1; + public const int ConcreteClass = 2; + public void ObjOrClass(object _) => this.Value = Object; + public void ObjOrClass(Overloaded _) => this.Value = ConcreteClass; + + public const int Base = ConcreteClass + 1; + public const int Derived = Base + 1; + public void BaseOrDerived(Base _) => this.Value = Base; + public void BaseOrDerived(Derived _) => this.Value = Derived; } } } From aeed0d2d3d5ea089a7ea456e1394e07be79f1faf Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 28 Jan 2019 11:53:25 -0800 Subject: [PATCH 005/240] added a regression test for #881 https://github.com/pythonnet/pythonnet/issues/811 --- src/embed_tests/TestInstanceWrapping.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index f2206710b..ca5386366 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -61,6 +61,19 @@ public void OverloadResolution_BaseOrDerived() { } } + // regression test for https://github.com/pythonnet/pythonnet/issues/811 + [Test] + public void OverloadResolution_UnknownToObject() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithSelf = PythonEngine.Eval("lambda o: o.ObjOrClass(KeyError())"); + callWithSelf(o); + Assert.AreEqual(Overloaded.Object, overloaded.Value); + } + } + class Base {} class Derived: Base { } From fefe3de3f9cecc9f9d244023ab58d0a240daeab4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 4 Feb 2019 20:28:16 -0800 Subject: [PATCH 006/240] generate more useful message, when a .NET overload can't be found, that matches Python parameter types --- src/embed_tests/TestCallbacks.cs | 14 +++++++++++++- src/runtime/methodbinder.cs | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index 51d3f939d..99db401ae 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -7,7 +7,7 @@ namespace Python.EmbeddingTest { public class TestCallbacks { [OneTimeSetUp] public void SetUp() { - PythonEngine.Initialize(); + string path = Environment.GetEnvironmentVariable("PATH"); } [OneTimeTearDown] @@ -41,5 +41,17 @@ public void TestReentry() { } Assert.AreEqual(expected: 42, actual: passed); } + + [Test] + public void TestNoOverloadException() { + int passed = 0; + var aFunctionThatCallsIntoPython = new Action(value => passed = value); + using (Py.GIL()) { + dynamic callWith42 = PythonEngine.Eval("lambda f: f([42])"); + var error = Assert.Throws(() => callWith42(aFunctionThatCallsIntoPython.ToPython())); + Assert.AreEqual("TypeError", error.PythonTypeName); + StringAssert.EndsWith("()", error.Message); + } + } } } diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 5e800c36f..eed39fa42 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -512,6 +512,26 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i { value += $" for {methodinfo[0].Name}"; } + + long argCount = Runtime.PyTuple_Size(args); + value += ": ("; + for(long argIndex = 0; argIndex < argCount; argIndex++) { + var arg = Runtime.PyTuple_GetItem(args, argIndex); + if (arg != IntPtr.Zero) { + var type = Runtime.PyObject_Type(arg); + if (type != IntPtr.Zero) { + var description = Runtime.PyObject_Unicode(type); + if (description != IntPtr.Zero) { + value += Runtime.GetManagedString(description); + Runtime.XDecref(description); + } + } + } + + if (argIndex + 1 < argCount) + value += ", "; + } + value += ")"; Exceptions.SetError(Exceptions.TypeError, value); return IntPtr.Zero; } From e9712b4b514637bdc788f9c149298b0a9b7d5150 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Feb 2019 22:38:50 -0800 Subject: [PATCH 007/240] when converting to object, wrap values of unknown type into PyObject instead of failing This enables overload resolution with object parameters to behave the same way PyObject parameters behave - e.g. allow any Python object to be passed as PyObject as fallback. Resolves #811 --- src/runtime/converter.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 11c67bf82..1883dc32b 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -382,12 +382,9 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return ToArray(value, typeof(object[]), out result, setError); } - if (setError) - { - Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object"); - } - - return false; + Runtime.XIncref(value); // PyObject() assumes ownership + result = new PyObject(value); + return true; } // Conversion to 'Type' is done using the same mappings as above for objects. From 5c9fa40107d048835632cfe0d79d2a0b5335775f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Feb 2019 22:40:59 -0800 Subject: [PATCH 008/240] provide detailed error message, when an overload can't be found when calling C# from Python Related: #811, #265, #782 --- src/runtime/methodbinder.cs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index eed39fa42..ef2e20700 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Reflection; +using System.Text; namespace Python.Runtime { @@ -507,32 +508,36 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i if (binding == null) { - var value = "No method matches given arguments"; + var value = new StringBuilder("No method matches given arguments"); if (methodinfo != null && methodinfo.Length > 0) { - value += $" for {methodinfo[0].Name}"; + value.Append($" for {methodinfo[0].Name}"); } long argCount = Runtime.PyTuple_Size(args); - value += ": ("; + value.Append(": ("); for(long argIndex = 0; argIndex < argCount; argIndex++) { var arg = Runtime.PyTuple_GetItem(args, argIndex); if (arg != IntPtr.Zero) { var type = Runtime.PyObject_Type(arg); if (type != IntPtr.Zero) { - var description = Runtime.PyObject_Unicode(type); - if (description != IntPtr.Zero) { - value += Runtime.GetManagedString(description); - Runtime.XDecref(description); + try { + var description = Runtime.PyObject_Unicode(type); + if (description != IntPtr.Zero) { + value.Append(Runtime.GetManagedString(description)); + Runtime.XDecref(description); + } + } finally { + Runtime.XDecref(type); } } } if (argIndex + 1 < argCount) - value += ", "; + value.Append(", "); } - value += ")"; - Exceptions.SetError(Exceptions.TypeError, value); + value.Append(')'); + Exceptions.SetError(Exceptions.TypeError, value.ToString()); return IntPtr.Zero; } From 069c4cc8fcb445d6d02b5243e495b3b4bb66a36f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Feb 2019 22:43:17 -0800 Subject: [PATCH 009/240] generate unofficial .NET Standard-compatible packages for Python.Runtime for Linux and Windows targets Related: #804 #244 --- global.json | 5 + pythonnet.15.sln | 207 ++++++++++++++++++++++++-- src/runtime/Python.Runtime.15.csproj | 73 ++++----- src/runtime/Python.Runtime.Ref.csproj | 33 ++++ 4 files changed, 261 insertions(+), 57 deletions(-) create mode 100644 global.json create mode 100644 src/runtime/Python.Runtime.Ref.csproj diff --git a/global.json b/global.json new file mode 100644 index 000000000..73fa45c8d --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "MSBuild.Sdk.Extras": "1.6.65" + } +} diff --git a/pythonnet.15.sln b/pythonnet.15.sln index f2015e480..cac63ec12 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -2,188 +2,377 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26730.3 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.15", "src/runtime/Python.Runtime.15.csproj", "{2759F4FF-716B-4828-916F-50FA86613DFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.15", "src\runtime\Python.Runtime.15.csproj", "{2759F4FF-716B-4828-916F-50FA86613DFC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.EmbeddingTest.15", "src/embed_tests/Python.EmbeddingTest.15.csproj", "{66B8D01A-9906-452A-B09E-BF75EA76468F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.EmbeddingTest.15", "src\embed_tests\Python.EmbeddingTest.15.csproj", "{66B8D01A-9906-452A-B09E-BF75EA76468F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "clrmodule.15", "src/clrmodule/clrmodule.15.csproj", "{E08678D4-9A52-4AD5-B63D-8EBC7399981B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "clrmodule.15", "src\clrmodule\clrmodule.15.csproj", "{E08678D4-9A52-4AD5-B63D-8EBC7399981B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Console.15", "src/console/Console.15.csproj", "{CDAD305F-8E72-492C-A314-64CF58D472A0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Console.15", "src\console\Console.15.csproj", "{CDAD305F-8E72-492C-A314-64CF58D472A0}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Test.15", "src/testing/Python.Test.15.csproj", "{F94B547A-E97E-4500-8D53-B4D64D076E5F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Test.15", "src\testing\Python.Test.15.csproj", "{F94B547A-E97E-4500-8D53-B4D64D076E5F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{B6E8FE48-C755-496E-9BE0-34A60B77CA03}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.Ref", "src\runtime\Python.Runtime.Ref.csproj", "{9AE47FC5-A656-4071-85BE-ABE97EB6F38B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + DebugMono|Any CPU = DebugMono|Any CPU DebugMono|x64 = DebugMono|x64 DebugMono|x86 = DebugMono|x86 + DebugMonoPY3|Any CPU = DebugMonoPY3|Any CPU DebugMonoPY3|x64 = DebugMonoPY3|x64 DebugMonoPY3|x86 = DebugMonoPY3|x86 + DebugWin|Any CPU = DebugWin|Any CPU DebugWin|x64 = DebugWin|x64 DebugWin|x86 = DebugWin|x86 + DebugWinPY3|Any CPU = DebugWinPY3|Any CPU DebugWinPY3|x64 = DebugWinPY3|x64 DebugWinPY3|x86 = DebugWinPY3|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + ReleaseMono|Any CPU = ReleaseMono|Any CPU ReleaseMono|x64 = ReleaseMono|x64 ReleaseMono|x86 = ReleaseMono|x86 + ReleaseMonoPY3|Any CPU = ReleaseMonoPY3|Any CPU ReleaseMonoPY3|x64 = ReleaseMonoPY3|x64 ReleaseMonoPY3|x86 = ReleaseMonoPY3|x86 + ReleaseWin|Any CPU = ReleaseWin|Any CPU ReleaseWin|x64 = ReleaseWin|x64 ReleaseWin|x86 = ReleaseWin|x86 + ReleaseWinPY3|Any CPU = ReleaseWinPY3|Any CPU ReleaseWinPY3|x64 = ReleaseWinPY3|x64 ReleaseWinPY3|x86 = ReleaseWinPY3|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.ActiveCfg = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.Build.0 = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.ActiveCfg = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.Build.0 = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.ActiveCfg = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.Build.0 = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.ActiveCfg = DebugMono|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.Build.0 = DebugMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.ActiveCfg = DebugMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.Build.0 = DebugMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.ActiveCfg = DebugMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.Build.0 = DebugMono|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.Build.0 = DebugMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.ActiveCfg = DebugWin|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.Build.0 = DebugWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.Build.0 = DebugWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.Build.0 = DebugWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.Build.0 = DebugWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.ActiveCfg = Debug3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.Build.0 = Debug3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.Build.0 = DebugWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.ActiveCfg = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.Build.0 = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.ActiveCfg = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.Build.0 = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.ActiveCfg = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.Build.0 = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.Build.0 = ReleaseMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.ActiveCfg = ReleaseMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.Build.0 = ReleaseMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.ActiveCfg = ReleaseMono|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.Build.0 = ReleaseMono|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.Build.0 = ReleaseMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.Build.0 = ReleaseWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.Build.0 = ReleaseWinPY3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.ActiveCfg = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.Build.0 = Release3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|Any CPU {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|Any CPU + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.Build.0 = DebugWinPY3|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.Build.0 = DebugWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.ActiveCfg = DebugMono|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.Build.0 = DebugMono|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.ActiveCfg = DebugMono|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.Build.0 = DebugMono|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.ActiveCfg = DebugWin|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.Build.0 = DebugWin|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.ActiveCfg = DebugWin|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.Build.0 = DebugWin|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.Build.0 = ReleaseWinPY3|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.Build.0 = ReleaseWinPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.ActiveCfg = DebugWinPY3|x64 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.Build.0 = DebugWinPY3|x64 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.ActiveCfg = DebugWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.Build.0 = DebugWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x64.ActiveCfg = DebugMono|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x86.ActiveCfg = DebugMono|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.ActiveCfg = DebugWin|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.Build.0 = DebugWin|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.ActiveCfg = DebugWin|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.Build.0 = DebugWin|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.Build.0 = ReleaseWinPY3|x64 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.Build.0 = ReleaseWinPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.ActiveCfg = DebugWinPY3|x64 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.Build.0 = DebugWinPY3|x64 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.ActiveCfg = DebugWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.Build.0 = DebugWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.ActiveCfg = DebugMono|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.Build.0 = DebugMono|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.ActiveCfg = DebugMono|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.Build.0 = DebugMono|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.ActiveCfg = DebugWin|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.Build.0 = DebugWin|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.ActiveCfg = DebugWin|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.Build.0 = DebugWin|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.Build.0 = ReleaseWinPY3|x64 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.Build.0 = ReleaseWinPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.Build.0 = DebugWinPY3|x64 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.Build.0 = DebugWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.ActiveCfg = DebugMono|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.Build.0 = DebugMono|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.ActiveCfg = DebugMono|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.Build.0 = DebugMono|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.ActiveCfg = DebugWin|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.Build.0 = DebugWin|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.ActiveCfg = DebugWin|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.Build.0 = DebugWin|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.Build.0 = ReleaseWinPY3|x64 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.Build.0 = ReleaseWinPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|Any CPU.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|Any CPU.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x64.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x64.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x86.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x86.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|Any CPU.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|Any CPU.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x64.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x64.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x86.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x86.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|Any CPU.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|Any CPU.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x64.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x64.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x86.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x86.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|Any CPU.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|Any CPU.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x64.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x64.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x86.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x86.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|Any CPU.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|Any CPU.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x64.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x64.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x86.ActiveCfg = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x86.Build.0 = Debug3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|Any CPU.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|Any CPU.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x64.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x64.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x86.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x86.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|Any CPU.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|Any CPU.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x64.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x64.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x86.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x86.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|Any CPU.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|Any CPU.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x64.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x64.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x86.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x86.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|Any CPU.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|Any CPU.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x64.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x64.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x86.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x86.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|Any CPU.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|Any CPU.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x64.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x64.Build.0 = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x86.ActiveCfg = Release3|Any CPU + {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x86.Build.0 = Release3|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 794645994..db857ec2f 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,14 +1,15 @@ - - + - net40;netstandard2.0 + netstandard2.0 + true + linux-x64;win AnyCPU - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 - net45 + Debug3;Release3;DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Python.Runtime Python.Runtime - Python.Runtime + Python.Runtime.UnofficialNetStandard 2.4.0 + true false false false @@ -16,13 +17,11 @@ false false bin\ - false - $(OutputPath)\$(AssemblyName).xml - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml + $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml 1591;NU1701 ..\..\ $(SolutionDir)\bin\ - $(PythonBuildDir)\$(TargetFramework)\ + $(PythonBuildDir)\$(TargetFramework)\ 6 True ..\pythonnet.snk @@ -31,32 +30,25 @@ $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); $(DefineConstants);NETSTANDARD $(DefineConstants);TRACE;DEBUG - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.5\1.0.1\lib\net45\ $(PYTHONNET_PY2_VERSION) PYTHON27 $(PYTHONNET_PY3_VERSION) - PYTHON37 + PYTHON36 + + $(PYTHONNET_MULTIRUNTIME_DEFINE_CONSTANTS) + UCS2 + UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC + $(PYTHONNET_WIN_DEFINE_CONSTANTS) UCS2 $(PYTHONNET_MONO_DEFINE_CONSTANTS) UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC - $(PYTHONNET_INTEROP_FILE) - - - false - full - - - true - pdbonly - - true + false full - - true + true portable @@ -85,11 +77,15 @@ $(DefineConstants);PYTHON3;$(Python3Version);$(PythonWinDefineConstants);TRACE;DEBUG + + $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMultiRuntimeDefineConstants);TRACE;DEBUG + + + $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMultiRuntimeDefineConstants) + - - - - + + @@ -114,27 +110,8 @@ - - - - - - - - - - $(TargetPath) $(TargetDir)$(TargetName).pdb - - - - - - - - - diff --git a/src/runtime/Python.Runtime.Ref.csproj b/src/runtime/Python.Runtime.Ref.csproj new file mode 100644 index 000000000..2c54c95f6 --- /dev/null +++ b/src/runtime/Python.Runtime.Ref.csproj @@ -0,0 +1,33 @@ + + + + netstandard2.0 + Debug3;Release3 + false + true + Python.Runtime + Python.Runtime + True + + false + false + false + false + false + false + + $(PYTHONNET_PY2_VERSION) + PYTHON27 + $(PYTHONNET_PY3_VERSION) + PYTHON36 + + $(DefineConstants);XPLAT;NETSTANDARD;UCS2;$(Python3Version);PYTHON3 + + + + + + + + + From 2842d6b45bee09fbbb5b1f9e4a8f7da31c3f070c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 Feb 2019 16:10:31 -0800 Subject: [PATCH 010/240] replace linux-x64 target with generalized unix target --- src/runtime/Python.Runtime.15.csproj | 6 +++--- src/runtime/Python.Runtime.Ref.csproj | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index db857ec2f..008a65d5e 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,8 +1,8 @@ - + netstandard2.0 true - linux-x64;win + unix;win AnyCPU Debug3;Release3;DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Python.Runtime @@ -37,7 +37,7 @@ $(PYTHONNET_MULTIRUNTIME_DEFINE_CONSTANTS) UCS2 - UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC + UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC $(PYTHONNET_WIN_DEFINE_CONSTANTS) UCS2 diff --git a/src/runtime/Python.Runtime.Ref.csproj b/src/runtime/Python.Runtime.Ref.csproj index 2c54c95f6..11dbc77b9 100644 --- a/src/runtime/Python.Runtime.Ref.csproj +++ b/src/runtime/Python.Runtime.Ref.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -8,6 +8,7 @@ Python.Runtime Python.Runtime True + $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml false false From 80aa07fd4979825e3acd5485ed22e1a579fd470b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 12:44:54 -0800 Subject: [PATCH 011/240] switched from DllImport to GetDelegateForFunctionPointer for Python3 runtime bindings (dll loading not implemented) --- src/runtime/runtime.cs | 2274 ++++++++++++++++++++++++++++++++-------- 1 file changed, 1819 insertions(+), 455 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 863eb4034..780c868ea 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -713,172 +713,173 @@ 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 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(); #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - public static extern int Py_Main( + + public static int Py_Main( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv - ); + ) => Delegates.Py_Main(argc, argv +); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] public static extern int Py_Main(int argc, string[] argv); #endif - [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 IntPtr PyEval_GetBuiltins() => Delegates.PyEval_GetBuiltins(); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_GetGlobals(); + + internal static IntPtr 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); + + internal static int PyRun_SimpleString(string code) => Delegates.PyRun_SimpleString(code); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals); + + internal static IntPtr PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals) => Delegates.PyRun_String(code, st, globals, locals); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals); + + internal static IntPtr PyEval_EvalCode(IntPtr co, IntPtr globals, IntPtr locals) => Delegates.PyEval_EvalCode(co, globals, locals); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Py_CompileString(string code, string file, IntPtr tok); + + internal static IntPtr Py_CompileString(string code, string file, IntPtr tok) => Delegates.Py_CompileString(code, file, tok); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_ExecCodeModule(string name, IntPtr code); + + internal static IntPtr PyImport_ExecCodeModule(string name, IntPtr code) => Delegates.PyImport_ExecCodeModule(name, 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 PyClass_New(IntPtr bases, IntPtr dict, IntPtr name); + + internal static IntPtr PyClass_New(IntPtr bases, IntPtr dict, IntPtr name) => Delegates.PyClass_New(bases, dict, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyInstance_New(IntPtr cls, IntPtr args, IntPtr kw); + + internal static IntPtr PyInstance_New(IntPtr cls, IntPtr args, IntPtr kw) => Delegates.PyInstance_New(cls, args, kw); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyInstance_NewRaw(IntPtr cls, IntPtr dict); + + internal static IntPtr PyInstance_NewRaw(IntPtr cls, IntPtr dict) => Delegates.PyInstance_NewRaw(cls, dict); - [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); //==================================================================== @@ -941,45 +942,45 @@ 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, string name); + + internal static int PyObject_HasAttrString(IntPtr pointer, string name) => Delegates.PyObject_HasAttrString(pointer, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GetAttrString(IntPtr pointer, string name); + + internal static IntPtr PyObject_GetAttrString(IntPtr pointer, string name) => Delegates.PyObject_GetAttrString(pointer, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value); + + internal static int PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value) => Delegates.PyObject_SetAttrString(pointer, name, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_HasAttr(IntPtr pointer, IntPtr name); + + internal static int PyObject_HasAttr(IntPtr pointer, IntPtr name) => Delegates.PyObject_HasAttr(pointer, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name); + + internal static IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name) => Delegates.PyObject_GetAttr(pointer, name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value); + + 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_GetItem(IntPtr pointer, IntPtr key); + + internal static IntPtr PyObject_GetItem(IntPtr pointer, IntPtr key) => Delegates.PyObject_GetItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value); + + 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_DelItem(IntPtr pointer, IntPtr key); + + internal static int PyObject_DelItem(IntPtr pointer, IntPtr key) => Delegates.PyObject_DelItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GetIter(IntPtr op); + + internal static IntPtr PyObject_GetIter(IntPtr op) => Delegates.PyObject_GetIter(op); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw); + + internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args); + + internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args) => Delegates.PyObject_CallObject(pointer, args); #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid); + + 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) { @@ -1010,49 +1011,48 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) internal static extern int PyObject_Compare(IntPtr value1, IntPtr value2); #endif - [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); + + internal static int PyObject_IsTrue(IntPtr pointer) => Delegates.PyObject_IsTrue(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_Not(IntPtr 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 IntPtr PyObject_Hash(IntPtr op); + + internal static IntPtr 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); #if PYTHON3 - [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); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyObject_Unicode(IntPtr pointer); #endif - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Dir(IntPtr pointer); + + internal static IntPtr PyObject_Dir(IntPtr pointer) => Delegates.PyObject_Dir(pointer); //==================================================================== @@ -1060,22 +1060,21 @@ internal static long PyObject_Size(IntPtr pointer) //==================================================================== #if PYTHON3 - [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); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr PyNumber_Int(IntPtr ob); #endif - [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(IntPtr ob) { @@ -1100,21 +1099,17 @@ internal static IntPtr PyInt_FromInt64(long value) } #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromLong")] - private static extern IntPtr PyInt_FromLong(IntPtr value); + + private static IntPtr PyInt_FromLong(IntPtr value) => Delegates.PyInt_FromLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsLong")] - internal static extern int PyInt_AsLong(IntPtr value); + + internal static int PyInt_AsLong(IntPtr value) => Delegates.PyInt_AsLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromString")] - internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); + + internal static IntPtr PyInt_FromString(string value, IntPtr end, int radix) => Delegates.PyInt_FromString(value, end, radix); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_GetMax")] - internal static extern int PyInt_GetMax(); + + internal static int PyInt_GetMax() => Delegates.PyInt_GetMax(); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyInt_FromLong(IntPtr value); @@ -1134,219 +1129,219 @@ 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)] - internal static extern IntPtr PyLong_FromUnsignedLong(uint value); + + internal static IntPtr PyLong_FromUnsignedLong(uint value) => Delegates.PyLong_FromUnsignedLong(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); + + internal static IntPtr PyLong_FromString(string value, IntPtr end, int radix) => Delegates.PyLong_FromString(value, end, radix); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyLong_AsLong(IntPtr value); + + internal static int PyLong_AsLong(IntPtr value) => Delegates.PyLong_AsLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern uint PyLong_AsUnsignedLong(IntPtr value); + + internal static uint PyLong_AsUnsignedLong(IntPtr value) => Delegates.PyLong_AsUnsignedLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern long PyLong_AsLongLong(IntPtr value); + + internal static long PyLong_AsLongLong(IntPtr value) => Delegates.PyLong_AsLongLong(value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern ulong PyLong_AsUnsignedLongLong(IntPtr value); + + internal static ulong PyLong_AsUnsignedLongLong(IntPtr value) => Delegates.PyLong_AsUnsignedLongLong(value); internal static bool PyFloat_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyFloatType; } - [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 IntPtr PyFloat_FromString(IntPtr value, IntPtr junk) => Delegates.PyFloat_FromString(value, junk); - [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_Divide(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_Divide(IntPtr o1, IntPtr o2) => Delegates.PyNumber_Divide(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_InPlaceDivide(IntPtr o1, IntPtr o2); + + internal static IntPtr PyNumber_InPlaceDivide(IntPtr o1, IntPtr o2) => Delegates.PyNumber_InPlaceDivide(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 bool PySequence_Check(IntPtr pointer) => Delegates.PySequence_Check(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); + + private static IntPtr PySequence_GetItem(IntPtr pointer, IntPtr 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); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")] - private static extern IntPtr _PySequence_Size(IntPtr pointer); + + private static IntPtr _PySequence_Size(IntPtr pointer) => Delegates._PySequence_Size(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PySequence_Contains(IntPtr pointer, IntPtr item); + + internal static int PySequence_Contains(IntPtr pointer, IntPtr item) => Delegates.PySequence_Contains(pointer, 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); //==================================================================== @@ -1374,16 +1369,16 @@ internal static IntPtr PyString_FromString(string value) } #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyBytes_FromString(string op); + + internal static IntPtr PyBytes_FromString(string op) => Delegates.PyBytes_FromString(op); internal static long PyBytes_Size(IntPtr op) { return (long) _PyBytes_Size(op); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")] - private static extern IntPtr _PyBytes_Size(IntPtr op); + + private static IntPtr _PyBytes_Size(IntPtr op) => Delegates._PyBytes_Size(op); internal static IntPtr PyBytes_AS_STRING(IntPtr ob) { @@ -1395,20 +1390,20 @@ internal static IntPtr PyString_FromStringAndSize(string value, long size) return _PyString_FromStringAndSize(value, new IntPtr(size)); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_FromStringAndSize")] - internal static extern IntPtr _PyString_FromStringAndSize( + + internal static IntPtr _PyString_FromStringAndSize( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, IntPtr size - ); + ) => Delegates._PyString_FromStringAndSize(value, size +); 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); #elif PYTHON2 internal static IntPtr PyString_FromStringAndSize(string value, long size) { @@ -1431,23 +1426,24 @@ internal static bool PyUnicode_Check(IntPtr ob) } #if PYTHON3 - [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) { return PyUnicode_FromKindAndData(kind, s, new IntPtr(size)); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr PyUnicode_FromKindAndData( + + private static IntPtr PyUnicode_FromKindAndData( int kind, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, IntPtr size - ); + ) => Delegates.PyUnicode_FromKindAndData(kind, s, size +); internal static IntPtr PyUnicode_FromUnicode(string s, long size) { @@ -1459,14 +1455,14 @@ 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); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyUnicode_FromOrdinal(int c); + + internal static IntPtr PyUnicode_FromOrdinal(int c) => Delegates.PyUnicode_FromOrdinal(c); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = PyUnicodeEntryPoint + "FromObject")] @@ -1559,58 +1555,58 @@ 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 IntPtr PyDictProxy_New(IntPtr dict); + + internal static IntPtr PyDictProxy_New(IntPtr dict) => Delegates.PyDictProxy_New(dict); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key); + + internal static IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key) => Delegates.PyDict_GetItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_GetItemString(IntPtr pointer, string key); + + internal static IntPtr PyDict_GetItemString(IntPtr pointer, string key) => Delegates.PyDict_GetItemString(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value); + + internal static int PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value) => Delegates.PyDict_SetItem(pointer, key, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_SetItemString(IntPtr pointer, string key, IntPtr value); + + internal static int PyDict_SetItemString(IntPtr pointer, string key, IntPtr value) => Delegates.PyDict_SetItemString(pointer, key, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_DelItem(IntPtr pointer, IntPtr key); + + internal static int PyDict_DelItem(IntPtr pointer, IntPtr key) => Delegates.PyDict_DelItem(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_DelItemString(IntPtr pointer, string key); + + internal static int PyDict_DelItemString(IntPtr pointer, string key) => Delegates.PyDict_DelItemString(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyMapping_HasKey(IntPtr pointer, IntPtr key); + + internal static int PyMapping_HasKey(IntPtr pointer, IntPtr key) => Delegates.PyMapping_HasKey(pointer, key); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Keys(IntPtr pointer); + + internal static IntPtr PyDict_Keys(IntPtr pointer) => Delegates.PyDict_Keys(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Values(IntPtr pointer); + + internal static IntPtr PyDict_Values(IntPtr pointer) => Delegates.PyDict_Values(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Items(IntPtr pointer); + + internal static IntPtr PyDict_Items(IntPtr pointer) => Delegates.PyDict_Items(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyDict_Copy(IntPtr pointer); + + internal static IntPtr PyDict_Copy(IntPtr pointer) => Delegates.PyDict_Copy(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyDict_Update(IntPtr pointer, IntPtr other); + + internal static int PyDict_Update(IntPtr pointer, IntPtr other) => Delegates.PyDict_Update(pointer, other); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyDict_Clear(IntPtr pointer); + + 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); //==================================================================== @@ -1627,68 +1623,68 @@ 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 IntPtr PyList_GetItem(IntPtr pointer, long index) { return PyList_GetItem(pointer, new IntPtr(index)); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr PyList_GetItem(IntPtr pointer, IntPtr index); + + private static IntPtr PyList_GetItem(IntPtr 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(IntPtr pointer, long index, IntPtr value) { return PyList_Insert(pointer, new IntPtr(index), value); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern int PyList_Insert(IntPtr pointer, IntPtr index, IntPtr value); + + private static int PyList_Insert(IntPtr pointer, IntPtr index, IntPtr value) => Delegates.PyList_Insert(pointer, index, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Append(IntPtr pointer, IntPtr value); + + internal static int PyList_Append(IntPtr pointer, IntPtr value) => Delegates.PyList_Append(pointer, value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Reverse(IntPtr pointer); + + internal static int PyList_Reverse(IntPtr pointer) => Delegates.PyList_Reverse(pointer); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyList_Sort(IntPtr pointer); + + internal static int PyList_Sort(IntPtr 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); + + private static int PyList_SetSlice(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value) => Delegates.PyList_SetSlice(pointer, start, end, value); internal static long PyList_Size(IntPtr pointer) { return (long) _PyList_Size(pointer); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")] - private static extern IntPtr _PyList_Size(IntPtr pointer); + + private static IntPtr _PyList_Size(IntPtr pointer) => Delegates._PyList_Size(pointer); //==================================================================== // Python tuple API @@ -1704,40 +1700,40 @@ 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 IntPtr PyTuple_GetItem(IntPtr pointer, long index) { return PyTuple_GetItem(pointer, new IntPtr(index)); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr PyTuple_GetItem(IntPtr pointer, IntPtr index); + + private static IntPtr PyTuple_GetItem(IntPtr 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); + + private static IntPtr _PyTuple_Size(IntPtr pointer) => Delegates._PyTuple_Size(pointer); //==================================================================== @@ -1756,53 +1752,54 @@ 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); + + internal static IntPtr PyIter_Next(IntPtr pointer) => Delegates.PyIter_Next(pointer); //==================================================================== // Python module API //==================================================================== - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyModule_New(string name); + + internal static IntPtr PyModule_New(string name) => Delegates.PyModule_New(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern string PyModule_GetName(IntPtr module); + + internal static string PyModule_GetName(IntPtr module) => Delegates.PyModule_GetName(module); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyModule_GetDict(IntPtr module); + + internal static IntPtr PyModule_GetDict(IntPtr 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); #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyModule_Create2(IntPtr module, int apiver); + + internal static IntPtr PyModule_Create2(IntPtr module, int apiver) => Delegates.PyModule_Create2(module, apiver); #endif - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_Import(IntPtr name); + + internal static IntPtr PyImport_Import(IntPtr name) => Delegates.PyImport_Import(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_ImportModule(string name); + + internal static IntPtr PyImport_ImportModule(string name) => Delegates.PyImport_ImportModule(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_ReloadModule(IntPtr module); + + internal static IntPtr PyImport_ReloadModule(IntPtr module) => Delegates.PyImport_ReloadModule(module); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_AddModule(string name); + + internal static IntPtr PyImport_AddModule(string name) => Delegates.PyImport_AddModule(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyImport_GetModuleDict(); + + internal static IntPtr PyImport_GetModuleDict() => Delegates.PyImport_GetModuleDict(); #if PYTHON3 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PySys_SetArgvEx( + + internal static void PySys_SetArgvEx( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, int updatepath - ); + ) => Delegates.PySys_SetArgvEx(argc, argv, updatepath +); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PySys_SetArgvEx( @@ -1812,11 +1809,11 @@ int updatepath ); #endif - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PySys_GetObject(string name); + + internal static IntPtr PySys_GetObject(string name) => Delegates.PySys_GetObject(name); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PySys_SetObject(string name, IntPtr ob); + + internal static int PySys_SetObject(string name, IntPtr ob) => Delegates.PySys_SetObject(name, ob); //==================================================================== @@ -1828,11 +1825,11 @@ 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); + + internal static void PyType_Modified(IntPtr type) => Delegates.PyType_Modified(type); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern bool PyType_IsSubtype(IntPtr t1, IntPtr t2); + + internal static bool PyType_IsSubtype(IntPtr t1, IntPtr t2) => Delegates.PyType_IsSubtype(t1, t2); internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) { @@ -1840,43 +1837,43 @@ internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) return (t == tp) || PyType_IsSubtype(t, tp); } - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kw); + + 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); - [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 IntPtr _PyObject_GetDictPtr(IntPtr obj) => Delegates._PyObject_GetDictPtr(obj); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GC_New(IntPtr tp); + + internal static IntPtr PyObject_GC_New(IntPtr tp) => Delegates.PyObject_GC_New(tp); - [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); //==================================================================== @@ -1888,70 +1885,1437 @@ 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, string message); + + internal static void PyErr_SetString(IntPtr ob, string message) => Delegates.PyErr_SetString(ob, message); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_SetObject(IntPtr ob, IntPtr message); + + internal static void PyErr_SetObject(IntPtr ob, IntPtr message) => Delegates.PyErr_SetObject(ob, message); - [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); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb); + + internal static void PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_NormalizeException(ob, val, 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(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + + internal static void PyErr_Fetch(ref IntPtr ob, ref IntPtr val, ref IntPtr tb) => Delegates.PyErr_Fetch(ref ob, ref val, ref 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(); //==================================================================== // 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); + + public static class Delegates + { + static Delegates() + { + Py_IncRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(_PythonDll))); + Py_DecRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(_PythonDll))); + Py_Initialize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(_PythonDll))); + Py_InitializeEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(_PythonDll))); + Py_IsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(_PythonDll))); + Py_Finalize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(_PythonDll))); + Py_NewInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(_PythonDll))); + Py_EndInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(_PythonDll))); + PyThreadState_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(_PythonDll))); + PyThreadState_Get = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(_PythonDll))); + PyThread_get_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(_PythonDll))); + PyThread_get_thread_ident = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(_PythonDll))); + PyThread_set_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(_PythonDll))); + PyThreadState_Swap = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(_PythonDll))); + PyGILState_Ensure = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(_PythonDll))); + PyGILState_Release = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(_PythonDll))); + PyGILState_GetThisThreadState = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(_PythonDll))); + Py_Main = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(_PythonDll))); + PyEval_InitThreads = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(_PythonDll))); + PyEval_ThreadsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(_PythonDll))); + PyEval_AcquireLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(_PythonDll))); + PyEval_ReleaseLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(_PythonDll))); + PyEval_AcquireThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(_PythonDll))); + PyEval_ReleaseThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(_PythonDll))); + PyEval_SaveThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(_PythonDll))); + PyEval_RestoreThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(_PythonDll))); + PyEval_GetBuiltins = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(_PythonDll))); + PyEval_GetGlobals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(_PythonDll))); + PyEval_GetLocals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(_PythonDll))); + Py_GetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(_PythonDll))); + Py_SetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(_PythonDll))); + Py_GetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(_PythonDll))); + Py_SetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(_PythonDll))); + Py_GetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(_PythonDll))); + Py_SetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(_PythonDll))); + Py_GetVersion = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(_PythonDll))); + Py_GetPlatform = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(_PythonDll))); + Py_GetCopyright = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(_PythonDll))); + Py_GetCompiler = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(_PythonDll))); + Py_GetBuildInfo = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(_PythonDll))); + PyRun_SimpleString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_SimpleString), GetUnmanagedDll(_PythonDll))); + PyRun_String = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_String), GetUnmanagedDll(_PythonDll))); + PyEval_EvalCode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(_PythonDll))); + Py_CompileString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_CompileString), GetUnmanagedDll(_PythonDll))); + PyImport_ExecCodeModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(_PythonDll))); + PyCFunction_NewEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(_PythonDll))); + PyCFunction_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(_PythonDll))); + PyClass_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyClass_New), GetUnmanagedDll(_PythonDll))); + PyInstance_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyInstance_New), GetUnmanagedDll(_PythonDll))); + PyInstance_NewRaw = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyInstance_NewRaw), GetUnmanagedDll(_PythonDll))); + PyMethod_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_New), GetUnmanagedDll(_PythonDll))); + PyObject_HasAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(_PythonDll))); + PyObject_GetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(_PythonDll))); + PyObject_SetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(_PythonDll))); + PyObject_HasAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(_PythonDll))); + PyObject_GetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(_PythonDll))); + PyObject_SetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(_PythonDll))); + PyObject_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(_PythonDll))); + PyObject_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(_PythonDll))); + PyObject_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(_PythonDll))); + PyObject_GetIter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(_PythonDll))); + PyObject_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(_PythonDll))); + PyObject_CallObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(_PythonDll))); + PyObject_RichCompareBool = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(_PythonDll))); + PyObject_IsInstance = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(_PythonDll))); + PyObject_IsSubclass = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(_PythonDll))); + PyCallable_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(_PythonDll))); + PyObject_IsTrue = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(_PythonDll))); + PyObject_Not = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(_PythonDll))); + _PyObject_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_SizeDelegate>(GetFunctionByName("PyObject_Size", GetUnmanagedDll(_PythonDll))); + PyObject_Hash = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(_PythonDll))); + PyObject_Repr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(_PythonDll))); + PyObject_Str = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(_PythonDll))); + PyObject_Unicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyObject_Str", GetUnmanagedDll(_PythonDll))); + PyObject_Dir = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(_PythonDll))); + PyNumber_Int = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_Long", GetUnmanagedDll(_PythonDll))); + PyNumber_Long = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(_PythonDll))); + PyNumber_Float = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(_PythonDll))); + PyNumber_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(_PythonDll))); + PyInt_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(_PythonDll))); + PyInt_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(_PythonDll))); + PyInt_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(_PythonDll))); + PyInt_GetMax = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_GetMax", GetUnmanagedDll(_PythonDll))); + PyLong_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(_PythonDll))); + PyLong_FromUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(_PythonDll))); + PyLong_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(_PythonDll))); + PyLong_FromLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(_PythonDll))); + PyLong_FromUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(_PythonDll))); + PyLong_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(_PythonDll))); + PyLong_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(_PythonDll))); + PyLong_AsUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLong), GetUnmanagedDll(_PythonDll))); + PyLong_AsLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(_PythonDll))); + PyLong_AsUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(_PythonDll))); + PyFloat_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(_PythonDll))); + PyFloat_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(_PythonDll))); + PyFloat_AsDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(_PythonDll))); + PyNumber_Add = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(_PythonDll))); + PyNumber_Subtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(_PythonDll))); + PyNumber_Multiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(_PythonDll))); + PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Divide), GetUnmanagedDll(_PythonDll))); + PyNumber_And = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(_PythonDll))); + PyNumber_Xor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(_PythonDll))); + PyNumber_Or = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(_PythonDll))); + PyNumber_Lshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(_PythonDll))); + PyNumber_Rshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(_PythonDll))); + PyNumber_Power = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(_PythonDll))); + PyNumber_Remainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceAdd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceSubtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceMultiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceDivide), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceAnd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceXor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceOr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceLshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceRshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlacePower = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceRemainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(_PythonDll))); + PyNumber_Negative = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(_PythonDll))); + PyNumber_Positive = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(_PythonDll))); + PyNumber_Invert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(_PythonDll))); + PySequence_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(_PythonDll))); + PySequence_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(_PythonDll))); + PySequence_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(_PythonDll))); + PySequence_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(_PythonDll))); + PySequence_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(_PythonDll))); + PySequence_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(_PythonDll))); + PySequence_DelSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(_PythonDll))); + _PySequence_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_SizeDelegate>(GetFunctionByName("PySequence_Size", GetUnmanagedDll(_PythonDll))); + PySequence_Contains = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(_PythonDll))); + PySequence_Concat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(_PythonDll))); + PySequence_Repeat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(_PythonDll))); + PySequence_Index = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(_PythonDll))); + _PySequence_Count = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_CountDelegate>(GetFunctionByName("PySequence_Count", GetUnmanagedDll(_PythonDll))); + PySequence_Tuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(_PythonDll))); + PySequence_List = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(_PythonDll))); + PyBytes_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(_PythonDll))); + _PyBytes_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyBytes_SizeDelegate>(GetFunctionByName("PyBytes_Size", GetUnmanagedDll(_PythonDll))); + _PyString_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyString_FromStringAndSizeDelegate>(GetFunctionByName("PyUnicode_FromStringAndSize", GetUnmanagedDll(_PythonDll))); + PyUnicode_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(_PythonDll))); + PyUnicode_FromObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(_PythonDll))); + PyUnicode_FromEncodedObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(_PythonDll))); + PyUnicode_FromKindAndData = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(_PythonDll))); + _PyUnicode_GetSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyUnicode_GetSizeDelegate>(GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(_PythonDll))); + PyUnicode_AsUnicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(_PythonDll))); + PyUnicode_FromOrdinal = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(_PythonDll))); + PyDict_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(_PythonDll))); + PyDictProxy_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(_PythonDll))); + PyDict_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(_PythonDll))); + PyDict_GetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(_PythonDll))); + PyDict_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(_PythonDll))); + PyDict_SetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(_PythonDll))); + PyDict_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(_PythonDll))); + PyDict_DelItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(_PythonDll))); + PyMapping_HasKey = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(_PythonDll))); + PyDict_Keys = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(_PythonDll))); + PyDict_Values = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(_PythonDll))); + PyDict_Items = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(_PythonDll))); + PyDict_Copy = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(_PythonDll))); + PyDict_Update = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(_PythonDll))); + PyDict_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(_PythonDll))); + _PyDict_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyDict_SizeDelegate>(GetFunctionByName("PyDict_Size", GetUnmanagedDll(_PythonDll))); + PyList_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(_PythonDll))); + PyList_AsTuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(_PythonDll))); + PyList_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(_PythonDll))); + PyList_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(_PythonDll))); + PyList_Insert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(_PythonDll))); + PyList_Append = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(_PythonDll))); + PyList_Reverse = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(_PythonDll))); + PyList_Sort = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(_PythonDll))); + PyList_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(_PythonDll))); + PyList_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(_PythonDll))); + _PyList_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyList_SizeDelegate>(GetFunctionByName("PyList_Size", GetUnmanagedDll(_PythonDll))); + PyTuple_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(_PythonDll))); + PyTuple_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(_PythonDll))); + PyTuple_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(_PythonDll))); + PyTuple_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(_PythonDll))); + _PyTuple_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyTuple_SizeDelegate>(GetFunctionByName("PyTuple_Size", GetUnmanagedDll(_PythonDll))); + PyIter_Next = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(_PythonDll))); + PyModule_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(_PythonDll))); + PyModule_GetName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(_PythonDll))); + PyModule_GetDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(_PythonDll))); + PyModule_GetFilename = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(_PythonDll))); + PyModule_Create2 = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(_PythonDll))); + PyImport_Import = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(_PythonDll))); + PyImport_ImportModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(_PythonDll))); + PyImport_ReloadModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(_PythonDll))); + PyImport_AddModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(_PythonDll))); + PyImport_GetModuleDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(_PythonDll))); + PySys_SetArgvEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(_PythonDll))); + PySys_GetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(_PythonDll))); + PySys_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(_PythonDll))); + PyType_Modified = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(_PythonDll))); + PyType_IsSubtype = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(_PythonDll))); + PyType_GenericNew = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(_PythonDll))); + PyType_GenericAlloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(_PythonDll))); + PyType_Ready = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(_PythonDll))); + _PyType_Lookup = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyType_LookupDelegate>(GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(_PythonDll))); + PyObject_GenericGetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(_PythonDll))); + PyObject_GenericSetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(_PythonDll))); + _PyObject_GetDictPtr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(_PythonDll))); + PyObject_GC_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_New), GetUnmanagedDll(_PythonDll))); + PyObject_GC_Del = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(_PythonDll))); + PyObject_GC_Track = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll))); + PyObject_GC_UnTrack = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll))); + PyMem_Malloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(_PythonDll))); + PyMem_Realloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(_PythonDll))); + PyMem_Free = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(_PythonDll))); + PyErr_SetString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(_PythonDll))); + PyErr_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(_PythonDll))); + PyErr_SetFromErrno = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(_PythonDll))); + PyErr_SetNone = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(_PythonDll))); + PyErr_ExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(_PythonDll))); + PyErr_GivenExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(_PythonDll))); + PyErr_NormalizeException = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(_PythonDll))); + PyErr_Occurred = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(_PythonDll))); + PyErr_Fetch = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(_PythonDll))); + PyErr_Restore = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(_PythonDll))); + PyErr_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(_PythonDll))); + PyErr_Print = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(_PythonDll))); + PyMethod_Self = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(_PythonDll))); + PyMethod_Function = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(_PythonDll))); + } + + static global::System.IntPtr GetUnmanagedDll(string libraryName) + { + throw new NotImplementedException(); + } + + static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) + { + throw new NotImplementedException(); + } + + internal static Py_IncRefDelegate Py_IncRef { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_IncRefDelegate(IntPtr ob); + + internal static Py_DecRefDelegate Py_DecRef { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_DecRefDelegate(IntPtr ob); + + internal static Py_InitializeDelegate Py_Initialize { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_InitializeDelegate(); + + internal static Py_InitializeExDelegate Py_InitializeEx { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_InitializeExDelegate(int initsigs); + + internal static Py_IsInitializedDelegate Py_IsInitialized { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int Py_IsInitializedDelegate(); + + internal static Py_FinalizeDelegate Py_Finalize { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_FinalizeDelegate(); + + internal static Py_NewInterpreterDelegate Py_NewInterpreter { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_NewInterpreterDelegate(); + + internal static Py_EndInterpreterDelegate Py_EndInterpreter { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_EndInterpreterDelegate(IntPtr threadState); + + internal static PyThreadState_NewDelegate PyThreadState_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyThreadState_NewDelegate(IntPtr istate); + + internal static PyThreadState_GetDelegate PyThreadState_Get { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyThreadState_GetDelegate(); + + internal static PyThread_get_key_valueDelegate PyThread_get_key_value { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyThread_get_key_valueDelegate(IntPtr key); + + internal static PyThread_get_thread_identDelegate PyThread_get_thread_ident { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyThread_get_thread_identDelegate(); + + internal static PyThread_set_key_valueDelegate PyThread_set_key_value { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyThread_set_key_valueDelegate(IntPtr key, IntPtr value); + + internal static PyThreadState_SwapDelegate PyThreadState_Swap { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyThreadState_SwapDelegate(IntPtr key); + + internal static PyGILState_EnsureDelegate PyGILState_Ensure { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyGILState_EnsureDelegate(); + + internal static PyGILState_ReleaseDelegate PyGILState_Release { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyGILState_ReleaseDelegate(IntPtr gs); + + internal static PyGILState_GetThisThreadStateDelegate PyGILState_GetThisThreadState { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyGILState_GetThisThreadStateDelegate(); + + internal static Py_MainDelegate Py_Main { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int Py_MainDelegate( + int argc, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv + ); + + internal static PyEval_InitThreadsDelegate PyEval_InitThreads { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_InitThreadsDelegate(); + + internal static PyEval_ThreadsInitializedDelegate PyEval_ThreadsInitialized { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyEval_ThreadsInitializedDelegate(); + + internal static PyEval_AcquireLockDelegate PyEval_AcquireLock { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_AcquireLockDelegate(); + + internal static PyEval_ReleaseLockDelegate PyEval_ReleaseLock { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_ReleaseLockDelegate(); + + internal static PyEval_AcquireThreadDelegate PyEval_AcquireThread { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_AcquireThreadDelegate(IntPtr tstate); + + internal static PyEval_ReleaseThreadDelegate PyEval_ReleaseThread { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_ReleaseThreadDelegate(IntPtr tstate); + + internal static PyEval_SaveThreadDelegate PyEval_SaveThread { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyEval_SaveThreadDelegate(); + + internal static PyEval_RestoreThreadDelegate PyEval_RestoreThread { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyEval_RestoreThreadDelegate(IntPtr tstate); + + internal static PyEval_GetBuiltinsDelegate PyEval_GetBuiltins { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyEval_GetBuiltinsDelegate(); + + internal static PyEval_GetGlobalsDelegate PyEval_GetGlobals { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyEval_GetGlobalsDelegate(); + + internal static PyEval_GetLocalsDelegate PyEval_GetLocals { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyEval_GetLocalsDelegate(); + + internal static Py_GetProgramNameDelegate Py_GetProgramName { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetProgramNameDelegate(); + + internal static Py_SetProgramNameDelegate Py_SetProgramName { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_SetProgramNameDelegate(IntPtr name); + + internal static Py_GetPythonHomeDelegate Py_GetPythonHome { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetPythonHomeDelegate(); + + internal static Py_SetPythonHomeDelegate Py_SetPythonHome { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_SetPythonHomeDelegate(IntPtr home); + + internal static Py_GetPathDelegate Py_GetPath { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetPathDelegate(); + + internal static Py_SetPathDelegate Py_SetPath { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void Py_SetPathDelegate(IntPtr home); + + internal static Py_GetVersionDelegate Py_GetVersion { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetVersionDelegate(); + + internal static Py_GetPlatformDelegate Py_GetPlatform { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetPlatformDelegate(); + + internal static Py_GetCopyrightDelegate Py_GetCopyright { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetCopyrightDelegate(); + + internal static Py_GetCompilerDelegate Py_GetCompiler { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetCompilerDelegate(); + + internal static Py_GetBuildInfoDelegate Py_GetBuildInfo { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_GetBuildInfoDelegate(); + + internal static PyRun_SimpleStringDelegate PyRun_SimpleString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyRun_SimpleStringDelegate(string code); + + internal static PyRun_StringDelegate PyRun_String { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyRun_StringDelegate(string code, IntPtr st, IntPtr globals, IntPtr locals); + + internal static PyEval_EvalCodeDelegate PyEval_EvalCode { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyEval_EvalCodeDelegate(IntPtr co, IntPtr globals, IntPtr locals); + + internal static Py_CompileStringDelegate Py_CompileString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr Py_CompileStringDelegate(string code, string file, IntPtr tok); + + internal static PyImport_ExecCodeModuleDelegate PyImport_ExecCodeModule { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_ExecCodeModuleDelegate(string name, IntPtr code); + + internal static PyCFunction_NewExDelegate PyCFunction_NewEx { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyCFunction_NewExDelegate(IntPtr ml, IntPtr self, IntPtr mod); + + internal static PyCFunction_CallDelegate PyCFunction_Call { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyCFunction_CallDelegate(IntPtr func, IntPtr args, IntPtr kw); + + internal static PyClass_NewDelegate PyClass_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyClass_NewDelegate(IntPtr bases, IntPtr dict, IntPtr name); + + internal static PyInstance_NewDelegate PyInstance_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyInstance_NewDelegate(IntPtr cls, IntPtr args, IntPtr kw); + + internal static PyInstance_NewRawDelegate PyInstance_NewRaw { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyInstance_NewRawDelegate(IntPtr cls, IntPtr dict); + + internal static PyMethod_NewDelegate PyMethod_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMethod_NewDelegate(IntPtr func, IntPtr self, IntPtr cls); + + internal static PyObject_HasAttrStringDelegate PyObject_HasAttrString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_HasAttrStringDelegate(IntPtr pointer, string name); + + internal static PyObject_GetAttrStringDelegate PyObject_GetAttrString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GetAttrStringDelegate(IntPtr pointer, string name); + + internal static PyObject_SetAttrStringDelegate PyObject_SetAttrString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_SetAttrStringDelegate(IntPtr pointer, string name, IntPtr value); + + internal static PyObject_HasAttrDelegate PyObject_HasAttr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_HasAttrDelegate(IntPtr pointer, IntPtr name); + + internal static PyObject_GetAttrDelegate PyObject_GetAttr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GetAttrDelegate(IntPtr pointer, IntPtr name); + + internal static PyObject_SetAttrDelegate PyObject_SetAttr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_SetAttrDelegate(IntPtr pointer, IntPtr name, IntPtr value); + + internal static PyObject_GetItemDelegate PyObject_GetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GetItemDelegate(IntPtr pointer, IntPtr key); + + internal static PyObject_SetItemDelegate PyObject_SetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); + + internal static PyObject_DelItemDelegate PyObject_DelItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_DelItemDelegate(IntPtr pointer, IntPtr key); + + internal static PyObject_GetIterDelegate PyObject_GetIter { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GetIterDelegate(IntPtr op); + + internal static PyObject_CallDelegate PyObject_Call { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_CallDelegate(IntPtr pointer, IntPtr args, IntPtr kw); + + internal static PyObject_CallObjectDelegate PyObject_CallObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_CallObjectDelegate(IntPtr pointer, IntPtr args); + + internal static PyObject_RichCompareBoolDelegate PyObject_RichCompareBool { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_RichCompareBoolDelegate(IntPtr value1, IntPtr value2, int opid); + + internal static PyObject_IsInstanceDelegate PyObject_IsInstance { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_IsInstanceDelegate(IntPtr ob, IntPtr type); + + internal static PyObject_IsSubclassDelegate PyObject_IsSubclass { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_IsSubclassDelegate(IntPtr ob, IntPtr type); + + internal static PyCallable_CheckDelegate PyCallable_Check { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyCallable_CheckDelegate(IntPtr pointer); + + internal static PyObject_IsTrueDelegate PyObject_IsTrue { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_IsTrueDelegate(IntPtr pointer); + + internal static PyObject_NotDelegate PyObject_Not { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_NotDelegate(IntPtr pointer); + + internal static _PyObject_SizeDelegate _PyObject_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyObject_SizeDelegate(IntPtr pointer); + + internal static PyObject_HashDelegate PyObject_Hash { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_HashDelegate(IntPtr op); + + internal static PyObject_ReprDelegate PyObject_Repr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_ReprDelegate(IntPtr pointer); + + internal static PyObject_StrDelegate PyObject_Str { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_StrDelegate(IntPtr pointer); + + internal static PyObject_UnicodeDelegate PyObject_Unicode { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_UnicodeDelegate(IntPtr pointer); + + internal static PyObject_DirDelegate PyObject_Dir { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_DirDelegate(IntPtr pointer); + + internal static PyNumber_IntDelegate PyNumber_Int { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_IntDelegate(IntPtr ob); + + internal static PyNumber_LongDelegate PyNumber_Long { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_LongDelegate(IntPtr ob); + + internal static PyNumber_FloatDelegate PyNumber_Float { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_FloatDelegate(IntPtr ob); + + internal static PyNumber_CheckDelegate PyNumber_Check { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate bool PyNumber_CheckDelegate(IntPtr ob); + + internal static PyInt_FromLongDelegate PyInt_FromLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyInt_FromLongDelegate(IntPtr value); + + internal static PyInt_AsLongDelegate PyInt_AsLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyInt_AsLongDelegate(IntPtr value); + + internal static PyInt_FromStringDelegate PyInt_FromString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyInt_FromStringDelegate(string value, IntPtr end, int radix); + + internal static PyInt_GetMaxDelegate PyInt_GetMax { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyInt_GetMaxDelegate(); + + internal static PyLong_FromLongDelegate PyLong_FromLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromLongDelegate(long value); + + internal static PyLong_FromUnsignedLongDelegate PyLong_FromUnsignedLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromUnsignedLongDelegate(uint value); + + internal static PyLong_FromDoubleDelegate PyLong_FromDouble { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromDoubleDelegate(double value); + + internal static PyLong_FromLongLongDelegate PyLong_FromLongLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromLongLongDelegate(long value); + + internal static PyLong_FromUnsignedLongLongDelegate PyLong_FromUnsignedLongLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromUnsignedLongLongDelegate(ulong value); + + internal static PyLong_FromStringDelegate PyLong_FromString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyLong_FromStringDelegate(string value, IntPtr end, int radix); + + internal static PyLong_AsLongDelegate PyLong_AsLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyLong_AsLongDelegate(IntPtr value); + + internal static PyLong_AsUnsignedLongDelegate PyLong_AsUnsignedLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate uint PyLong_AsUnsignedLongDelegate(IntPtr value); + + internal static PyLong_AsLongLongDelegate PyLong_AsLongLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate long PyLong_AsLongLongDelegate(IntPtr value); + + internal static PyLong_AsUnsignedLongLongDelegate PyLong_AsUnsignedLongLong { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate ulong PyLong_AsUnsignedLongLongDelegate(IntPtr value); + + internal static PyFloat_FromDoubleDelegate PyFloat_FromDouble { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyFloat_FromDoubleDelegate(double value); + + internal static PyFloat_FromStringDelegate PyFloat_FromString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyFloat_FromStringDelegate(IntPtr value, IntPtr junk); + + internal static PyFloat_AsDoubleDelegate PyFloat_AsDouble { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate double PyFloat_AsDoubleDelegate(IntPtr ob); + + internal static PyNumber_AddDelegate PyNumber_Add { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_AddDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_SubtractDelegate PyNumber_Subtract { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_SubtractDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_MultiplyDelegate PyNumber_Multiply { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_MultiplyDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_DivideDelegate PyNumber_Divide { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_DivideDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_AndDelegate PyNumber_And { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_AndDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_XorDelegate PyNumber_Xor { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_XorDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_OrDelegate PyNumber_Or { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_OrDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_LshiftDelegate PyNumber_Lshift { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_LshiftDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_RshiftDelegate PyNumber_Rshift { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_RshiftDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_PowerDelegate PyNumber_Power { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_PowerDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_RemainderDelegate PyNumber_Remainder { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_RemainderDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceAddDelegate PyNumber_InPlaceAdd { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceAddDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceSubtractDelegate PyNumber_InPlaceSubtract { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceSubtractDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceMultiplyDelegate PyNumber_InPlaceMultiply { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceMultiplyDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceDivideDelegate PyNumber_InPlaceDivide { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceDivideDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceAndDelegate PyNumber_InPlaceAnd { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceAndDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceXorDelegate PyNumber_InPlaceXor { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceXorDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceOrDelegate PyNumber_InPlaceOr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceOrDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceLshiftDelegate PyNumber_InPlaceLshift { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceLshiftDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceRshiftDelegate PyNumber_InPlaceRshift { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceRshiftDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlacePowerDelegate PyNumber_InPlacePower { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlacePowerDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_InPlaceRemainderDelegate PyNumber_InPlaceRemainder { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InPlaceRemainderDelegate(IntPtr o1, IntPtr o2); + + internal static PyNumber_NegativeDelegate PyNumber_Negative { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_NegativeDelegate(IntPtr o1); + + internal static PyNumber_PositiveDelegate PyNumber_Positive { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_PositiveDelegate(IntPtr o1); + + internal static PyNumber_InvertDelegate PyNumber_Invert { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyNumber_InvertDelegate(IntPtr o1); + + internal static PySequence_CheckDelegate PySequence_Check { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate bool PySequence_CheckDelegate(IntPtr pointer); + + internal static PySequence_GetItemDelegate PySequence_GetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_GetItemDelegate(IntPtr pointer, IntPtr index); + + internal static PySequence_SetItemDelegate PySequence_SetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + + internal static PySequence_DelItemDelegate PySequence_DelItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_DelItemDelegate(IntPtr pointer, IntPtr index); + + internal static PySequence_GetSliceDelegate PySequence_GetSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_GetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); + + internal static PySequence_SetSliceDelegate PySequence_SetSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_SetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2, IntPtr v); + + internal static PySequence_DelSliceDelegate PySequence_DelSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_DelSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); + + internal static _PySequence_SizeDelegate _PySequence_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PySequence_SizeDelegate(IntPtr pointer); + + internal static PySequence_ContainsDelegate PySequence_Contains { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_ContainsDelegate(IntPtr pointer, IntPtr item); + + internal static PySequence_ConcatDelegate PySequence_Concat { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_ConcatDelegate(IntPtr pointer, IntPtr other); + + internal static PySequence_RepeatDelegate PySequence_Repeat { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_RepeatDelegate(IntPtr pointer, IntPtr count); + + internal static PySequence_IndexDelegate PySequence_Index { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySequence_IndexDelegate(IntPtr pointer, IntPtr item); + + internal static _PySequence_CountDelegate _PySequence_Count { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PySequence_CountDelegate(IntPtr pointer, IntPtr value); + + internal static PySequence_TupleDelegate PySequence_Tuple { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_TupleDelegate(IntPtr pointer); + + internal static PySequence_ListDelegate PySequence_List { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySequence_ListDelegate(IntPtr pointer); + + internal static PyBytes_FromStringDelegate PyBytes_FromString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyBytes_FromStringDelegate(string op); + + internal static _PyBytes_SizeDelegate _PyBytes_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyBytes_SizeDelegate(IntPtr op); + + internal static _PyString_FromStringAndSizeDelegate _PyString_FromStringAndSize { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyString_FromStringAndSizeDelegate( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, + IntPtr size + ); + + internal static PyUnicode_FromStringAndSizeDelegate PyUnicode_FromStringAndSize { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_FromStringAndSizeDelegate(IntPtr value, IntPtr size); + + internal static PyUnicode_FromObjectDelegate PyUnicode_FromObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_FromObjectDelegate(IntPtr ob); + + internal static PyUnicode_FromEncodedObjectDelegate PyUnicode_FromEncodedObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_FromEncodedObjectDelegate(IntPtr ob, IntPtr enc, IntPtr err); + + internal static PyUnicode_FromKindAndDataDelegate PyUnicode_FromKindAndData { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_FromKindAndDataDelegate( + int kind, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, + IntPtr size + ); + + internal static _PyUnicode_GetSizeDelegate _PyUnicode_GetSize { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyUnicode_GetSizeDelegate(IntPtr ob); + + internal static PyUnicode_AsUnicodeDelegate PyUnicode_AsUnicode { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_AsUnicodeDelegate(IntPtr ob); + + internal static PyUnicode_FromOrdinalDelegate PyUnicode_FromOrdinal { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyUnicode_FromOrdinalDelegate(int c); + + internal static PyDict_NewDelegate PyDict_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_NewDelegate(); + + internal static PyDictProxy_NewDelegate PyDictProxy_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDictProxy_NewDelegate(IntPtr dict); + + internal static PyDict_GetItemDelegate PyDict_GetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_GetItemDelegate(IntPtr pointer, IntPtr key); + + internal static PyDict_GetItemStringDelegate PyDict_GetItemString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_GetItemStringDelegate(IntPtr pointer, string key); + + internal static PyDict_SetItemDelegate PyDict_SetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyDict_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); + + internal static PyDict_SetItemStringDelegate PyDict_SetItemString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyDict_SetItemStringDelegate(IntPtr pointer, string key, IntPtr value); + + internal static PyDict_DelItemDelegate PyDict_DelItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyDict_DelItemDelegate(IntPtr pointer, IntPtr key); + + internal static PyDict_DelItemStringDelegate PyDict_DelItemString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyDict_DelItemStringDelegate(IntPtr pointer, string key); + + internal static PyMapping_HasKeyDelegate PyMapping_HasKey { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyMapping_HasKeyDelegate(IntPtr pointer, IntPtr key); + + internal static PyDict_KeysDelegate PyDict_Keys { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_KeysDelegate(IntPtr pointer); + + internal static PyDict_ValuesDelegate PyDict_Values { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_ValuesDelegate(IntPtr pointer); + + internal static PyDict_ItemsDelegate PyDict_Items { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_ItemsDelegate(IntPtr pointer); + + internal static PyDict_CopyDelegate PyDict_Copy { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyDict_CopyDelegate(IntPtr pointer); + + internal static PyDict_UpdateDelegate PyDict_Update { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyDict_UpdateDelegate(IntPtr pointer, IntPtr other); + + internal static PyDict_ClearDelegate PyDict_Clear { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyDict_ClearDelegate(IntPtr pointer); + + internal static _PyDict_SizeDelegate _PyDict_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyDict_SizeDelegate(IntPtr pointer); + + internal static PyList_NewDelegate PyList_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyList_NewDelegate(IntPtr size); + + internal static PyList_AsTupleDelegate PyList_AsTuple { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyList_AsTupleDelegate(IntPtr pointer); + + internal static PyList_GetItemDelegate PyList_GetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyList_GetItemDelegate(IntPtr pointer, IntPtr index); + + internal static PyList_SetItemDelegate PyList_SetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + + internal static PyList_InsertDelegate PyList_Insert { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_InsertDelegate(IntPtr pointer, IntPtr index, IntPtr value); + + internal static PyList_AppendDelegate PyList_Append { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_AppendDelegate(IntPtr pointer, IntPtr value); + + internal static PyList_ReverseDelegate PyList_Reverse { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_ReverseDelegate(IntPtr pointer); + + internal static PyList_SortDelegate PyList_Sort { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_SortDelegate(IntPtr pointer); + + internal static PyList_GetSliceDelegate PyList_GetSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyList_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); + + internal static PyList_SetSliceDelegate PyList_SetSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyList_SetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value); + + internal static _PyList_SizeDelegate _PyList_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyList_SizeDelegate(IntPtr pointer); + + internal static PyTuple_NewDelegate PyTuple_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyTuple_NewDelegate(IntPtr size); + + internal static PyTuple_GetItemDelegate PyTuple_GetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyTuple_GetItemDelegate(IntPtr pointer, IntPtr index); + + internal static PyTuple_SetItemDelegate PyTuple_SetItem { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyTuple_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + + internal static PyTuple_GetSliceDelegate PyTuple_GetSlice { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyTuple_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); + + internal static _PyTuple_SizeDelegate _PyTuple_Size { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyTuple_SizeDelegate(IntPtr pointer); + + internal static PyIter_NextDelegate PyIter_Next { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyIter_NextDelegate(IntPtr pointer); + + internal static PyModule_NewDelegate PyModule_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyModule_NewDelegate(string name); + + internal static PyModule_GetNameDelegate PyModule_GetName { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate string PyModule_GetNameDelegate(IntPtr module); + + internal static PyModule_GetDictDelegate PyModule_GetDict { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyModule_GetDictDelegate(IntPtr module); + + internal static PyModule_GetFilenameDelegate PyModule_GetFilename { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate string PyModule_GetFilenameDelegate(IntPtr module); + + internal static PyModule_Create2Delegate PyModule_Create2 { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyModule_Create2Delegate(IntPtr module, int apiver); + + internal static PyImport_ImportDelegate PyImport_Import { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_ImportDelegate(IntPtr name); + + internal static PyImport_ImportModuleDelegate PyImport_ImportModule { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_ImportModuleDelegate(string name); + + internal static PyImport_ReloadModuleDelegate PyImport_ReloadModule { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_ReloadModuleDelegate(IntPtr module); + + internal static PyImport_AddModuleDelegate PyImport_AddModule { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_AddModuleDelegate(string name); + + internal static PyImport_GetModuleDictDelegate PyImport_GetModuleDict { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyImport_GetModuleDictDelegate(); + + internal static PySys_SetArgvExDelegate PySys_SetArgvEx { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PySys_SetArgvExDelegate( + int argc, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, + int updatepath + ); + + internal static PySys_GetObjectDelegate PySys_GetObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PySys_GetObjectDelegate(string name); + + internal static PySys_SetObjectDelegate PySys_SetObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PySys_SetObjectDelegate(string name, IntPtr ob); + + internal static PyType_ModifiedDelegate PyType_Modified { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyType_ModifiedDelegate(IntPtr type); + + internal static PyType_IsSubtypeDelegate PyType_IsSubtype { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate bool PyType_IsSubtypeDelegate(IntPtr t1, IntPtr t2); + + internal static PyType_GenericNewDelegate PyType_GenericNew { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyType_GenericNewDelegate(IntPtr type, IntPtr args, IntPtr kw); + + internal static PyType_GenericAllocDelegate PyType_GenericAlloc { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyType_GenericAllocDelegate(IntPtr type, IntPtr n); + + internal static PyType_ReadyDelegate PyType_Ready { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyType_ReadyDelegate(IntPtr type); + + internal static _PyType_LookupDelegate _PyType_Lookup { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyType_LookupDelegate(IntPtr type, IntPtr name); + + internal static PyObject_GenericGetAttrDelegate PyObject_GenericGetAttr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GenericGetAttrDelegate(IntPtr obj, IntPtr name); + + internal static PyObject_GenericSetAttrDelegate PyObject_GenericSetAttr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyObject_GenericSetAttrDelegate(IntPtr obj, IntPtr name, IntPtr value); + + internal static _PyObject_GetDictPtrDelegate _PyObject_GetDictPtr { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr _PyObject_GetDictPtrDelegate(IntPtr obj); + + internal static PyObject_GC_NewDelegate PyObject_GC_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyObject_GC_NewDelegate(IntPtr tp); + + internal static PyObject_GC_DelDelegate PyObject_GC_Del { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyObject_GC_DelDelegate(IntPtr tp); + + internal static PyObject_GC_TrackDelegate PyObject_GC_Track { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyObject_GC_TrackDelegate(IntPtr tp); + + internal static PyObject_GC_UnTrackDelegate PyObject_GC_UnTrack { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyObject_GC_UnTrackDelegate(IntPtr tp); + + internal static PyMem_MallocDelegate PyMem_Malloc { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMem_MallocDelegate(IntPtr size); + + internal static PyMem_ReallocDelegate PyMem_Realloc { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMem_ReallocDelegate(IntPtr ptr, IntPtr size); + + internal static PyMem_FreeDelegate PyMem_Free { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyMem_FreeDelegate(IntPtr ptr); + + internal static PyErr_SetStringDelegate PyErr_SetString { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_SetStringDelegate(IntPtr ob, string message); + + internal static PyErr_SetObjectDelegate PyErr_SetObject { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_SetObjectDelegate(IntPtr ob, IntPtr message); + + internal static PyErr_SetFromErrnoDelegate PyErr_SetFromErrno { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyErr_SetFromErrnoDelegate(IntPtr ob); + + internal static PyErr_SetNoneDelegate PyErr_SetNone { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_SetNoneDelegate(IntPtr ob); + + internal static PyErr_ExceptionMatchesDelegate PyErr_ExceptionMatches { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyErr_ExceptionMatchesDelegate(IntPtr exception); + + internal static PyErr_GivenExceptionMatchesDelegate PyErr_GivenExceptionMatches { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate int PyErr_GivenExceptionMatchesDelegate(IntPtr ob, IntPtr val); + + internal static PyErr_NormalizeExceptionDelegate PyErr_NormalizeException { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_NormalizeExceptionDelegate(IntPtr ob, IntPtr val, IntPtr tb); + + internal static PyErr_OccurredDelegate PyErr_Occurred { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyErr_OccurredDelegate(); + + internal static PyErr_FetchDelegate PyErr_Fetch { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_FetchDelegate(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + + internal static PyErr_RestoreDelegate PyErr_Restore { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_RestoreDelegate(IntPtr ob, IntPtr val, IntPtr tb); + + internal static PyErr_ClearDelegate PyErr_Clear { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_ClearDelegate(); + + internal static PyErr_PrintDelegate PyErr_Print { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyErr_PrintDelegate(); + + internal static PyMethod_SelfDelegate PyMethod_Self { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMethod_SelfDelegate(IntPtr ob); + + internal static PyMethod_FunctionDelegate PyMethod_Function { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMethod_FunctionDelegate(IntPtr ob); + // end of PY3 + + enum Py2 { } + + } } } From a335bdd90d73890e6f6a575618be3f6883ce4e82 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 15:23:05 -0800 Subject: [PATCH 012/240] removed dead code; fixed entry points for several functions --- src/runtime/runtime.cs | 83 +++++++++++------------------------------- 1 file changed, 21 insertions(+), 62 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 780c868ea..00796315c 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -6,6 +6,8 @@ namespace Python.Runtime { + using System.IO; + [SuppressUnmanagedCodeSecurity] internal static class NativeMethods { @@ -869,18 +871,6 @@ public static int Py_Main( internal static IntPtr PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw) => Delegates.PyCFunction_Call(func, args, kw); - - internal static IntPtr PyClass_New(IntPtr bases, IntPtr dict, IntPtr name) => Delegates.PyClass_New(bases, dict, name); - - - internal static IntPtr PyInstance_New(IntPtr cls, IntPtr args, IntPtr kw) => Delegates.PyInstance_New(cls, args, kw); - - - internal static IntPtr PyInstance_NewRaw(IntPtr cls, IntPtr dict) => Delegates.PyInstance_NewRaw(cls, dict); - - - internal static IntPtr PyMethod_New(IntPtr func, IntPtr self, IntPtr cls) => Delegates.PyMethod_New(func, self, cls); - //==================================================================== // Python abstract object API @@ -1107,9 +1097,6 @@ internal static IntPtr PyInt_FromInt64(long value) internal static IntPtr PyInt_FromString(string value, IntPtr end, int radix) => Delegates.PyInt_FromString(value, end, radix); - - - internal static int PyInt_GetMax() => Delegates.PyInt_GetMax(); #elif PYTHON2 [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr PyInt_FromLong(IntPtr value); @@ -1864,9 +1851,6 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) internal static IntPtr _PyObject_GetDictPtr(IntPtr obj) => Delegates._PyObject_GetDictPtr(obj); - internal static IntPtr PyObject_GC_New(IntPtr tp) => Delegates.PyObject_GC_New(tp); - - internal static void PyObject_GC_Del(IntPtr tp) => Delegates.PyObject_GC_Del(tp); @@ -2002,10 +1986,6 @@ static Delegates() PyImport_ExecCodeModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(_PythonDll))); PyCFunction_NewEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(_PythonDll))); PyCFunction_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(_PythonDll))); - PyClass_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyClass_New), GetUnmanagedDll(_PythonDll))); - PyInstance_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyInstance_New), GetUnmanagedDll(_PythonDll))); - PyInstance_NewRaw = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyInstance_NewRaw), GetUnmanagedDll(_PythonDll))); - PyMethod_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_New), GetUnmanagedDll(_PythonDll))); PyObject_HasAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(_PythonDll))); PyObject_GetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(_PythonDll))); PyObject_SetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(_PythonDll))); @@ -2037,7 +2017,6 @@ static Delegates() PyInt_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(_PythonDll))); PyInt_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(_PythonDll))); PyInt_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(_PythonDll))); - PyInt_GetMax = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_GetMax", GetUnmanagedDll(_PythonDll))); PyLong_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(_PythonDll))); PyLong_FromUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(_PythonDll))); PyLong_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(_PythonDll))); @@ -2054,7 +2033,7 @@ static Delegates() PyNumber_Add = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(_PythonDll))); PyNumber_Subtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(_PythonDll))); PyNumber_Multiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(_PythonDll))); - PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Divide), GetUnmanagedDll(_PythonDll))); + PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_TrueDivide", GetUnmanagedDll(_PythonDll))); PyNumber_And = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(_PythonDll))); PyNumber_Xor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(_PythonDll))); PyNumber_Or = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(_PythonDll))); @@ -2065,7 +2044,7 @@ static Delegates() PyNumber_InPlaceAdd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(_PythonDll))); PyNumber_InPlaceSubtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(_PythonDll))); PyNumber_InPlaceMultiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceDivide), GetUnmanagedDll(_PythonDll))); + PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_InPlaceTrueDivide", GetUnmanagedDll(_PythonDll))); PyNumber_InPlaceAnd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(_PythonDll))); PyNumber_InPlaceXor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(_PythonDll))); PyNumber_InPlaceOr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(_PythonDll))); @@ -2156,7 +2135,6 @@ static Delegates() PyObject_GenericGetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(_PythonDll))); PyObject_GenericSetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(_PythonDll))); _PyObject_GetDictPtr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(_PythonDll))); - PyObject_GC_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_New), GetUnmanagedDll(_PythonDll))); PyObject_GC_Del = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(_PythonDll))); PyObject_GC_Track = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll))); PyObject_GC_UnTrack = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll))); @@ -2179,14 +2157,25 @@ static Delegates() PyMethod_Function = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(_PythonDll))); } - static global::System.IntPtr GetUnmanagedDll(string libraryName) - { - throw new NotImplementedException(); + static global::System.IntPtr GetUnmanagedDll(string libraryName) { + if (string.IsNullOrEmpty(Path.GetExtension(libraryName))) { + libraryName = + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? libraryName + ".dll" + : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? $"lib{libraryName}.so" + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"lib{libraryName}.dylib" + : throw new PlatformNotSupportedException(); + } + IntPtr handle = NativeMethods.LoadLibrary(libraryName); + if (handle == IntPtr.Zero) + throw new FileLoadException(); + return handle; } - static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) - { - throw new NotImplementedException(); + static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) { + IntPtr functionPointer = NativeMethods.GetProcAddress(libraryHandle, functionName); + if (functionPointer == IntPtr.Zero) + throw new EntryPointNotFoundException($"Function {functionName} was not found"); + return functionPointer; } internal static Py_IncRefDelegate Py_IncRef { get; } @@ -2427,26 +2416,6 @@ public delegate int Py_MainDelegate( [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate IntPtr PyCFunction_CallDelegate(IntPtr func, IntPtr args, IntPtr kw); - internal static PyClass_NewDelegate PyClass_New { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyClass_NewDelegate(IntPtr bases, IntPtr dict, IntPtr name); - - internal static PyInstance_NewDelegate PyInstance_New { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyInstance_NewDelegate(IntPtr cls, IntPtr args, IntPtr kw); - - internal static PyInstance_NewRawDelegate PyInstance_NewRaw { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyInstance_NewRawDelegate(IntPtr cls, IntPtr dict); - - internal static PyMethod_NewDelegate PyMethod_New { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMethod_NewDelegate(IntPtr func, IntPtr self, IntPtr cls); - internal static PyObject_HasAttrStringDelegate PyObject_HasAttrString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] @@ -2602,11 +2571,6 @@ public delegate int Py_MainDelegate( [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate IntPtr PyInt_FromStringDelegate(string value, IntPtr end, int radix); - internal static PyInt_GetMaxDelegate PyInt_GetMax { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyInt_GetMaxDelegate(); - internal static PyLong_FromLongDelegate PyLong_FromLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] @@ -3208,11 +3172,6 @@ int updatepath [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate IntPtr _PyObject_GetDictPtrDelegate(IntPtr obj); - internal static PyObject_GC_NewDelegate PyObject_GC_New { get; } - - [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GC_NewDelegate(IntPtr tp); - internal static PyObject_GC_DelDelegate PyObject_GC_Del { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] From 672258f590c6ad16db7f327f2690698cd3d4b38f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 15:36:32 -0800 Subject: [PATCH 013/240] allow consumer to override Python DLL path --- src/runtime/runtime.cs | 438 ++++++++++++++++++++--------------------- 1 file changed, 219 insertions(+), 219 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 00796315c..5adc02638 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -179,7 +179,7 @@ public class Runtime // We needs to replace all public constants to static readonly fields to allow // binary substitution of different Python.Runtime.dll builds in a target application. - public static readonly string PythonDLL = _PythonDll; + public static string PythonDLL { get; set; } = _PythonDll; #if PYTHON_WITHOUT_ENABLE_SHARED && !NETSTANDARD internal const string _PythonDll = "__Internal"; @@ -393,9 +393,9 @@ internal static void Initialize(bool initSigs = false) IntPtr dllLocal = IntPtr.Zero; - if (_PythonDll != "__Internal") + if (PythonDLL != "__Internal") { - dllLocal = NativeMethods.LoadLibrary(_PythonDll); + dllLocal = NativeMethods.LoadLibrary(PythonDLL); } _PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dllLocal, "_PyObject_NextNotImplemented"); @@ -1939,222 +1939,222 @@ public static class Delegates { static Delegates() { - Py_IncRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(_PythonDll))); - Py_DecRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(_PythonDll))); - Py_Initialize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(_PythonDll))); - Py_InitializeEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(_PythonDll))); - Py_IsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(_PythonDll))); - Py_Finalize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(_PythonDll))); - Py_NewInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(_PythonDll))); - Py_EndInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(_PythonDll))); - PyThreadState_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(_PythonDll))); - PyThreadState_Get = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(_PythonDll))); - PyThread_get_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(_PythonDll))); - PyThread_get_thread_ident = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(_PythonDll))); - PyThread_set_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(_PythonDll))); - PyThreadState_Swap = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(_PythonDll))); - PyGILState_Ensure = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(_PythonDll))); - PyGILState_Release = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(_PythonDll))); - PyGILState_GetThisThreadState = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(_PythonDll))); - Py_Main = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(_PythonDll))); - PyEval_InitThreads = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(_PythonDll))); - PyEval_ThreadsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(_PythonDll))); - PyEval_AcquireLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(_PythonDll))); - PyEval_ReleaseLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(_PythonDll))); - PyEval_AcquireThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(_PythonDll))); - PyEval_ReleaseThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(_PythonDll))); - PyEval_SaveThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(_PythonDll))); - PyEval_RestoreThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(_PythonDll))); - PyEval_GetBuiltins = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(_PythonDll))); - PyEval_GetGlobals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(_PythonDll))); - PyEval_GetLocals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(_PythonDll))); - Py_GetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(_PythonDll))); - Py_SetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(_PythonDll))); - Py_GetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(_PythonDll))); - Py_SetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(_PythonDll))); - Py_GetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(_PythonDll))); - Py_SetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(_PythonDll))); - Py_GetVersion = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(_PythonDll))); - Py_GetPlatform = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(_PythonDll))); - Py_GetCopyright = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(_PythonDll))); - Py_GetCompiler = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(_PythonDll))); - Py_GetBuildInfo = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(_PythonDll))); - PyRun_SimpleString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_SimpleString), GetUnmanagedDll(_PythonDll))); - PyRun_String = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_String), GetUnmanagedDll(_PythonDll))); - PyEval_EvalCode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(_PythonDll))); - Py_CompileString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_CompileString), GetUnmanagedDll(_PythonDll))); - PyImport_ExecCodeModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(_PythonDll))); - PyCFunction_NewEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(_PythonDll))); - PyCFunction_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(_PythonDll))); - PyObject_HasAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(_PythonDll))); - PyObject_GetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(_PythonDll))); - PyObject_SetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(_PythonDll))); - PyObject_HasAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(_PythonDll))); - PyObject_GetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(_PythonDll))); - PyObject_SetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(_PythonDll))); - PyObject_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(_PythonDll))); - PyObject_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(_PythonDll))); - PyObject_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(_PythonDll))); - PyObject_GetIter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(_PythonDll))); - PyObject_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(_PythonDll))); - PyObject_CallObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(_PythonDll))); - PyObject_RichCompareBool = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(_PythonDll))); - PyObject_IsInstance = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(_PythonDll))); - PyObject_IsSubclass = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(_PythonDll))); - PyCallable_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(_PythonDll))); - PyObject_IsTrue = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(_PythonDll))); - PyObject_Not = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(_PythonDll))); - _PyObject_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_SizeDelegate>(GetFunctionByName("PyObject_Size", GetUnmanagedDll(_PythonDll))); - PyObject_Hash = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(_PythonDll))); - PyObject_Repr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(_PythonDll))); - PyObject_Str = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(_PythonDll))); - PyObject_Unicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyObject_Str", GetUnmanagedDll(_PythonDll))); - PyObject_Dir = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(_PythonDll))); - PyNumber_Int = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_Long", GetUnmanagedDll(_PythonDll))); - PyNumber_Long = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(_PythonDll))); - PyNumber_Float = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(_PythonDll))); - PyNumber_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(_PythonDll))); - PyInt_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(_PythonDll))); - PyInt_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(_PythonDll))); - PyInt_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(_PythonDll))); - PyLong_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(_PythonDll))); - PyLong_FromUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(_PythonDll))); - PyLong_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(_PythonDll))); - PyLong_FromLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(_PythonDll))); - PyLong_FromUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(_PythonDll))); - PyLong_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(_PythonDll))); - PyLong_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(_PythonDll))); - PyLong_AsUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLong), GetUnmanagedDll(_PythonDll))); - PyLong_AsLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(_PythonDll))); - PyLong_AsUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(_PythonDll))); - PyFloat_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(_PythonDll))); - PyFloat_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(_PythonDll))); - PyFloat_AsDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(_PythonDll))); - PyNumber_Add = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(_PythonDll))); - PyNumber_Subtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(_PythonDll))); - PyNumber_Multiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(_PythonDll))); - PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_TrueDivide", GetUnmanagedDll(_PythonDll))); - PyNumber_And = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(_PythonDll))); - PyNumber_Xor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(_PythonDll))); - PyNumber_Or = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(_PythonDll))); - PyNumber_Lshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(_PythonDll))); - PyNumber_Rshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(_PythonDll))); - PyNumber_Power = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(_PythonDll))); - PyNumber_Remainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceAdd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceSubtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceMultiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_InPlaceTrueDivide", GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceAnd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceXor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceOr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceLshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceRshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlacePower = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(_PythonDll))); - PyNumber_InPlaceRemainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(_PythonDll))); - PyNumber_Negative = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(_PythonDll))); - PyNumber_Positive = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(_PythonDll))); - PyNumber_Invert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(_PythonDll))); - PySequence_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(_PythonDll))); - PySequence_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(_PythonDll))); - PySequence_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(_PythonDll))); - PySequence_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(_PythonDll))); - PySequence_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(_PythonDll))); - PySequence_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(_PythonDll))); - PySequence_DelSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(_PythonDll))); - _PySequence_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_SizeDelegate>(GetFunctionByName("PySequence_Size", GetUnmanagedDll(_PythonDll))); - PySequence_Contains = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(_PythonDll))); - PySequence_Concat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(_PythonDll))); - PySequence_Repeat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(_PythonDll))); - PySequence_Index = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(_PythonDll))); - _PySequence_Count = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_CountDelegate>(GetFunctionByName("PySequence_Count", GetUnmanagedDll(_PythonDll))); - PySequence_Tuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(_PythonDll))); - PySequence_List = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(_PythonDll))); - PyBytes_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(_PythonDll))); - _PyBytes_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyBytes_SizeDelegate>(GetFunctionByName("PyBytes_Size", GetUnmanagedDll(_PythonDll))); - _PyString_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyString_FromStringAndSizeDelegate>(GetFunctionByName("PyUnicode_FromStringAndSize", GetUnmanagedDll(_PythonDll))); - PyUnicode_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(_PythonDll))); - PyUnicode_FromObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(_PythonDll))); - PyUnicode_FromEncodedObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(_PythonDll))); - PyUnicode_FromKindAndData = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(_PythonDll))); - _PyUnicode_GetSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyUnicode_GetSizeDelegate>(GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(_PythonDll))); - PyUnicode_AsUnicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(_PythonDll))); - PyUnicode_FromOrdinal = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(_PythonDll))); - PyDict_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(_PythonDll))); - PyDictProxy_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(_PythonDll))); - PyDict_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(_PythonDll))); - PyDict_GetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(_PythonDll))); - PyDict_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(_PythonDll))); - PyDict_SetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(_PythonDll))); - PyDict_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(_PythonDll))); - PyDict_DelItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(_PythonDll))); - PyMapping_HasKey = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(_PythonDll))); - PyDict_Keys = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(_PythonDll))); - PyDict_Values = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(_PythonDll))); - PyDict_Items = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(_PythonDll))); - PyDict_Copy = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(_PythonDll))); - PyDict_Update = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(_PythonDll))); - PyDict_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(_PythonDll))); - _PyDict_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyDict_SizeDelegate>(GetFunctionByName("PyDict_Size", GetUnmanagedDll(_PythonDll))); - PyList_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(_PythonDll))); - PyList_AsTuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(_PythonDll))); - PyList_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(_PythonDll))); - PyList_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(_PythonDll))); - PyList_Insert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(_PythonDll))); - PyList_Append = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(_PythonDll))); - PyList_Reverse = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(_PythonDll))); - PyList_Sort = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(_PythonDll))); - PyList_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(_PythonDll))); - PyList_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(_PythonDll))); - _PyList_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyList_SizeDelegate>(GetFunctionByName("PyList_Size", GetUnmanagedDll(_PythonDll))); - PyTuple_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(_PythonDll))); - PyTuple_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(_PythonDll))); - PyTuple_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(_PythonDll))); - PyTuple_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(_PythonDll))); - _PyTuple_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyTuple_SizeDelegate>(GetFunctionByName("PyTuple_Size", GetUnmanagedDll(_PythonDll))); - PyIter_Next = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(_PythonDll))); - PyModule_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(_PythonDll))); - PyModule_GetName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(_PythonDll))); - PyModule_GetDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(_PythonDll))); - PyModule_GetFilename = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(_PythonDll))); - PyModule_Create2 = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(_PythonDll))); - PyImport_Import = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(_PythonDll))); - PyImport_ImportModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(_PythonDll))); - PyImport_ReloadModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(_PythonDll))); - PyImport_AddModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(_PythonDll))); - PyImport_GetModuleDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(_PythonDll))); - PySys_SetArgvEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(_PythonDll))); - PySys_GetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(_PythonDll))); - PySys_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(_PythonDll))); - PyType_Modified = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(_PythonDll))); - PyType_IsSubtype = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(_PythonDll))); - PyType_GenericNew = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(_PythonDll))); - PyType_GenericAlloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(_PythonDll))); - PyType_Ready = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(_PythonDll))); - _PyType_Lookup = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyType_LookupDelegate>(GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(_PythonDll))); - PyObject_GenericGetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(_PythonDll))); - PyObject_GenericSetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(_PythonDll))); - _PyObject_GetDictPtr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(_PythonDll))); - PyObject_GC_Del = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(_PythonDll))); - PyObject_GC_Track = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll))); - PyObject_GC_UnTrack = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll))); - PyMem_Malloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(_PythonDll))); - PyMem_Realloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(_PythonDll))); - PyMem_Free = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(_PythonDll))); - PyErr_SetString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(_PythonDll))); - PyErr_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(_PythonDll))); - PyErr_SetFromErrno = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(_PythonDll))); - PyErr_SetNone = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(_PythonDll))); - PyErr_ExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(_PythonDll))); - PyErr_GivenExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(_PythonDll))); - PyErr_NormalizeException = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(_PythonDll))); - PyErr_Occurred = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(_PythonDll))); - PyErr_Fetch = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(_PythonDll))); - PyErr_Restore = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(_PythonDll))); - PyErr_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(_PythonDll))); - PyErr_Print = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(_PythonDll))); - PyMethod_Self = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(_PythonDll))); - PyMethod_Function = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(_PythonDll))); + Py_IncRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(PythonDLL))); + Py_DecRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(PythonDLL))); + Py_Initialize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(PythonDLL))); + Py_InitializeEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(PythonDLL))); + Py_IsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(PythonDLL))); + Py_Finalize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(PythonDLL))); + Py_NewInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(PythonDLL))); + Py_EndInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(PythonDLL))); + PyThreadState_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(PythonDLL))); + PyThreadState_Get = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(PythonDLL))); + PyThread_get_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(PythonDLL))); + PyThread_get_thread_ident = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(PythonDLL))); + PyThread_set_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(PythonDLL))); + PyThreadState_Swap = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(PythonDLL))); + PyGILState_Ensure = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(PythonDLL))); + PyGILState_Release = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(PythonDLL))); + PyGILState_GetThisThreadState = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(PythonDLL))); + Py_Main = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(PythonDLL))); + PyEval_InitThreads = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(PythonDLL))); + PyEval_ThreadsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(PythonDLL))); + PyEval_AcquireLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(PythonDLL))); + PyEval_ReleaseLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(PythonDLL))); + PyEval_AcquireThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(PythonDLL))); + PyEval_ReleaseThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(PythonDLL))); + PyEval_SaveThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(PythonDLL))); + PyEval_RestoreThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(PythonDLL))); + PyEval_GetBuiltins = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(PythonDLL))); + PyEval_GetGlobals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(PythonDLL))); + PyEval_GetLocals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(PythonDLL))); + Py_GetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(PythonDLL))); + Py_SetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(PythonDLL))); + Py_GetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(PythonDLL))); + Py_SetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(PythonDLL))); + Py_GetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(PythonDLL))); + Py_SetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(PythonDLL))); + Py_GetVersion = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(PythonDLL))); + Py_GetPlatform = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(PythonDLL))); + Py_GetCopyright = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(PythonDLL))); + Py_GetCompiler = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(PythonDLL))); + Py_GetBuildInfo = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(PythonDLL))); + PyRun_SimpleString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_SimpleString), GetUnmanagedDll(PythonDLL))); + PyRun_String = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_String), GetUnmanagedDll(PythonDLL))); + PyEval_EvalCode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(PythonDLL))); + Py_CompileString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_CompileString), GetUnmanagedDll(PythonDLL))); + PyImport_ExecCodeModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(PythonDLL))); + PyCFunction_NewEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(PythonDLL))); + PyCFunction_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(PythonDLL))); + PyObject_HasAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_GetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_SetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_HasAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_SetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(PythonDLL))); + PyObject_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(PythonDLL))); + PyObject_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(PythonDLL))); + PyObject_GetIter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(PythonDLL))); + PyObject_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(PythonDLL))); + PyObject_CallObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(PythonDLL))); + PyObject_RichCompareBool = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(PythonDLL))); + PyObject_IsInstance = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(PythonDLL))); + PyObject_IsSubclass = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(PythonDLL))); + PyCallable_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(PythonDLL))); + PyObject_IsTrue = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(PythonDLL))); + PyObject_Not = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(PythonDLL))); + _PyObject_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_SizeDelegate>(GetFunctionByName("PyObject_Size", GetUnmanagedDll(PythonDLL))); + PyObject_Hash = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(PythonDLL))); + PyObject_Repr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(PythonDLL))); + PyObject_Str = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(PythonDLL))); + PyObject_Unicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyObject_Str", GetUnmanagedDll(PythonDLL))); + PyObject_Dir = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(PythonDLL))); + PyNumber_Int = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_Long", GetUnmanagedDll(PythonDLL))); + PyNumber_Long = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(PythonDLL))); + PyNumber_Float = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(PythonDLL))); + PyNumber_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(PythonDLL))); + PyInt_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(PythonDLL))); + PyInt_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(PythonDLL))); + PyInt_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(PythonDLL))); + PyLong_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(PythonDLL))); + PyLong_FromLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(PythonDLL))); + PyLong_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(PythonDLL))); + PyFloat_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(PythonDLL))); + PyFloat_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(PythonDLL))); + PyFloat_AsDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(PythonDLL))); + PyNumber_Add = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(PythonDLL))); + PyNumber_Subtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(PythonDLL))); + PyNumber_Multiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(PythonDLL))); + PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_TrueDivide", GetUnmanagedDll(PythonDLL))); + PyNumber_And = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(PythonDLL))); + PyNumber_Xor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(PythonDLL))); + PyNumber_Or = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(PythonDLL))); + PyNumber_Lshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(PythonDLL))); + PyNumber_Rshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(PythonDLL))); + PyNumber_Power = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(PythonDLL))); + PyNumber_Remainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceAdd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceSubtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceMultiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_InPlaceTrueDivide", GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceAnd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceXor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceOr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceLshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceRshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlacePower = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceRemainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(PythonDLL))); + PyNumber_Negative = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(PythonDLL))); + PyNumber_Positive = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(PythonDLL))); + PyNumber_Invert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(PythonDLL))); + PySequence_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(PythonDLL))); + PySequence_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(PythonDLL))); + PySequence_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(PythonDLL))); + PySequence_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(PythonDLL))); + PySequence_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(PythonDLL))); + PySequence_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(PythonDLL))); + PySequence_DelSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(PythonDLL))); + _PySequence_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_SizeDelegate>(GetFunctionByName("PySequence_Size", GetUnmanagedDll(PythonDLL))); + PySequence_Contains = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(PythonDLL))); + PySequence_Concat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(PythonDLL))); + PySequence_Repeat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(PythonDLL))); + PySequence_Index = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(PythonDLL))); + _PySequence_Count = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_CountDelegate>(GetFunctionByName("PySequence_Count", GetUnmanagedDll(PythonDLL))); + PySequence_Tuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(PythonDLL))); + PySequence_List = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(PythonDLL))); + PyBytes_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(PythonDLL))); + _PyBytes_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyBytes_SizeDelegate>(GetFunctionByName("PyBytes_Size", GetUnmanagedDll(PythonDLL))); + _PyString_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyString_FromStringAndSizeDelegate>(GetFunctionByName("PyUnicode_FromStringAndSize", GetUnmanagedDll(PythonDLL))); + PyUnicode_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromEncodedObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromKindAndData = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(PythonDLL))); + _PyUnicode_GetSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyUnicode_GetSizeDelegate>(GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(PythonDLL))); + PyUnicode_AsUnicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromOrdinal = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(PythonDLL))); + PyDict_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(PythonDLL))); + PyDictProxy_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(PythonDLL))); + PyDict_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(PythonDLL))); + PyDict_GetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(PythonDLL))); + PyDict_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(PythonDLL))); + PyDict_SetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(PythonDLL))); + PyDict_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(PythonDLL))); + PyDict_DelItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(PythonDLL))); + PyMapping_HasKey = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(PythonDLL))); + PyDict_Keys = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(PythonDLL))); + PyDict_Values = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(PythonDLL))); + PyDict_Items = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(PythonDLL))); + PyDict_Copy = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(PythonDLL))); + PyDict_Update = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(PythonDLL))); + PyDict_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(PythonDLL))); + _PyDict_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyDict_SizeDelegate>(GetFunctionByName("PyDict_Size", GetUnmanagedDll(PythonDLL))); + PyList_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(PythonDLL))); + PyList_AsTuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(PythonDLL))); + PyList_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(PythonDLL))); + PyList_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(PythonDLL))); + PyList_Insert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(PythonDLL))); + PyList_Append = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(PythonDLL))); + PyList_Reverse = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(PythonDLL))); + PyList_Sort = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(PythonDLL))); + PyList_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(PythonDLL))); + PyList_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(PythonDLL))); + _PyList_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyList_SizeDelegate>(GetFunctionByName("PyList_Size", GetUnmanagedDll(PythonDLL))); + PyTuple_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(PythonDLL))); + PyTuple_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(PythonDLL))); + PyTuple_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(PythonDLL))); + PyTuple_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(PythonDLL))); + _PyTuple_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyTuple_SizeDelegate>(GetFunctionByName("PyTuple_Size", GetUnmanagedDll(PythonDLL))); + PyIter_Next = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(PythonDLL))); + PyModule_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(PythonDLL))); + PyModule_GetName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(PythonDLL))); + PyModule_GetDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(PythonDLL))); + PyModule_GetFilename = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(PythonDLL))); + PyModule_Create2 = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(PythonDLL))); + PyImport_Import = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(PythonDLL))); + PyImport_ImportModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(PythonDLL))); + PyImport_ReloadModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(PythonDLL))); + PyImport_AddModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(PythonDLL))); + PyImport_GetModuleDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(PythonDLL))); + PySys_SetArgvEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(PythonDLL))); + PySys_GetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(PythonDLL))); + PySys_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(PythonDLL))); + PyType_Modified = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(PythonDLL))); + PyType_IsSubtype = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(PythonDLL))); + PyType_GenericNew = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(PythonDLL))); + PyType_GenericAlloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(PythonDLL))); + PyType_Ready = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(PythonDLL))); + _PyType_Lookup = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyType_LookupDelegate>(GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(PythonDLL))); + PyObject_GenericGetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GenericSetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(PythonDLL))); + _PyObject_GetDictPtr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(PythonDLL))); + PyObject_GC_Del = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(PythonDLL))); + PyObject_GC_Track = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(PythonDLL))); + PyObject_GC_UnTrack = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(PythonDLL))); + PyMem_Malloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(PythonDLL))); + PyMem_Realloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(PythonDLL))); + PyMem_Free = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(PythonDLL))); + PyErr_SetString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(PythonDLL))); + PyErr_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(PythonDLL))); + PyErr_SetFromErrno = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(PythonDLL))); + PyErr_SetNone = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(PythonDLL))); + PyErr_ExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(PythonDLL))); + PyErr_GivenExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(PythonDLL))); + PyErr_NormalizeException = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(PythonDLL))); + PyErr_Occurred = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(PythonDLL))); + PyErr_Fetch = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(PythonDLL))); + PyErr_Restore = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(PythonDLL))); + PyErr_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(PythonDLL))); + PyErr_Print = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(PythonDLL))); + PyMethod_Self = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(PythonDLL))); + PyMethod_Function = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(PythonDLL))); } static global::System.IntPtr GetUnmanagedDll(string libraryName) { From 572334f376b4e740de14c4ddf0179a40e4c30d3b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 15:42:56 -0800 Subject: [PATCH 014/240] removed syntax, no-compileable with C# 6 --- src/runtime/runtime.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 5adc02638..a05bf7611 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -2163,7 +2163,7 @@ static Delegates() RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? libraryName + ".dll" : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? $"lib{libraryName}.so" : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"lib{libraryName}.dylib" - : throw new PlatformNotSupportedException(); + : Throw(new PlatformNotSupportedException()); } IntPtr handle = NativeMethods.LoadLibrary(libraryName); if (handle == IntPtr.Zero) @@ -2171,6 +2171,10 @@ static Delegates() return handle; } + static T Throw(Exception exception) { + throw exception; + } + static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) { IntPtr functionPointer = NativeMethods.GetProcAddress(libraryHandle, functionName); if (functionPointer == IntPtr.Zero) From 26590545aece3faa097611dce3b96dfbc7c54e34 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 15:43:34 -0800 Subject: [PATCH 015/240] when a Thunk can not be obtained, throw --- src/runtime/interop.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 4ae4b61e0..6ce6f5e06 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -468,7 +468,8 @@ internal static IntPtr GetThunk(MethodInfo method, string funcType = null) keepAlive.Add(d); return fp; } - return IntPtr.Zero; + + throw new NotSupportedException(); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] From 402c91b51a97c0458493e6db4db81b107df0fdb0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 16:52:03 -0800 Subject: [PATCH 016/240] removed platfrom-specific IFDEFs from runtime.cs --- src/runtime/CustomMarshaler.cs | 6 +- src/runtime/Python.Runtime.15.csproj | 8 +- src/runtime/runtime.cs | 198 +++++++++++++++------------ 3 files changed, 117 insertions(+), 95 deletions(-) diff --git a/src/runtime/CustomMarshaler.cs b/src/runtime/CustomMarshaler.cs index b51911816..90bb77a71 100644 --- a/src/runtime/CustomMarshaler.cs +++ b/src/runtime/CustomMarshaler.cs @@ -91,13 +91,13 @@ public static int GetUnicodeByteLength(IntPtr p) var len = 0; while (true) { - int c = Runtime._UCS == 2 + int c = Runtime.UCS == 2 ? Marshal.ReadInt16(p, len * 2) : Marshal.ReadInt32(p, len * 4); if (c == 0) { - return len * Runtime._UCS; + return len * Runtime.UCS; } checked { @@ -163,7 +163,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 * Runtime.UCS; IntPtr mem = Marshal.AllocHGlobal(memSize); try diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 008a65d5e..ee81caa03 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -36,13 +36,13 @@ PYTHON36 $(PYTHONNET_MULTIRUNTIME_DEFINE_CONSTANTS) - UCS2 - UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC + + MONO_LINUX;PYTHON_WITH_PYMALLOC $(PYTHONNET_WIN_DEFINE_CONSTANTS) - UCS2 + $(PYTHONNET_MONO_DEFINE_CONSTANTS) - UCS4;MONO_LINUX;PYTHON_WITH_PYMALLOC + MONO_LINUX;PYTHON_WITH_PYMALLOC false diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index a05bf7611..30244e587 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -11,51 +11,33 @@ namespace Python.Runtime [SuppressUnmanagedCodeSecurity] internal static class NativeMethods { -#if MONO_LINUX || MONO_OSX -#if NETSTANDARD private static int RTLD_NOW = 0x2; -#if MONO_LINUX - private static int RTLD_GLOBAL = 0x100; - private static IntPtr RTLD_DEFAULT = IntPtr.Zero; - private const string NativeDll = "libdl.so"; - public static IntPtr LoadLibrary(string fileName) +// MONO_LINUX + private static int LINUX_RTLD_GLOBAL = 0x100; + private static IntPtr LINUX_RTLD_DEFAULT = IntPtr.Zero; + private const string LinuxNativeDll = "libdl.so"; + public static IntPtr LinuxLoadLibrary(string fileName) { - return dlopen($"lib{fileName}.so", RTLD_NOW | RTLD_GLOBAL); + fileName = string.IsNullOrEmpty(System.IO.Path.GetExtension(fileName)) ? $"lib{fileName}.so" : fileName; + return Linux.dlopen(fileName, RTLD_NOW | LINUX_RTLD_GLOBAL); } -#elif MONO_OSX - private static int RTLD_GLOBAL = 0x8; - private const string NativeDll = "/usr/lib/libSystem.dylib"; - private static IntPtr RTLD_DEFAULT = new IntPtr(-2); +// MONO_OSX + private static int MAC_RTLD_GLOBAL = 0x8; + private const string MacNativeDll = "/usr/lib/libSystem.dylib"; + private static IntPtr MAC_RTLD_DEFAULT = new IntPtr(-2); - public static IntPtr LoadLibrary(string fileName) + public static IntPtr MacLoadLibrary(string fileName) { - return dlopen($"lib{fileName}.dylib", RTLD_NOW | RTLD_GLOBAL); + fileName = string.IsNullOrEmpty(System.IO.Path.GetExtension(fileName)) ? $"lib{fileName}.dylib" : fileName; + return Mac.dlopen(fileName, RTLD_NOW | MAC_RTLD_GLOBAL); } -#endif -#else - private static int RTLD_NOW = 0x2; - private static int RTLD_SHARED = 0x20; -#if MONO_OSX - private static IntPtr RTLD_DEFAULT = new IntPtr(-2); - private const string NativeDll = "__Internal"; -#elif MONO_LINUX - private static IntPtr RTLD_DEFAULT = IntPtr.Zero; - private const string NativeDll = "libdl.so"; -#endif - - public static IntPtr LoadLibrary(string fileName) - { - return dlopen(fileName, RTLD_NOW | RTLD_SHARED); - } -#endif - - public static void FreeLibrary(IntPtr handle) - { - dlclose(handle); - } + static readonly IntPtr RTLD_DEFAULT = + RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? LINUX_RTLD_DEFAULT + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MAC_RTLD_DEFAULT + : Throw(new PlatformNotSupportedException()); - public static IntPtr GetProcAddress(IntPtr dllHandle, string name) + public static IntPtr UnixGetProcAddress(IntPtr dllHandle, string name) { // look in the exe if dllHandle is NULL if (dllHandle == IntPtr.Zero) @@ -64,9 +46,19 @@ public static IntPtr GetProcAddress(IntPtr dllHandle, string name) } // clear previous errors if any - dlerror(); - IntPtr res = dlsym(dllHandle, name); - IntPtr errPtr = dlerror(); + IntPtr res, errPtr; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { + Linux.dlerror(); + res = Linux.dlsym(dllHandle, name); + errPtr = Linux.dlerror(); + } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { + Mac.dlerror(); + res = Mac.dlsym(dllHandle, name); + errPtr = Mac.dlerror(); + } else { + throw new PlatformNotSupportedException(); + } + if (errPtr != IntPtr.Zero) { throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr)); @@ -74,29 +66,82 @@ public static IntPtr GetProcAddress(IntPtr dllHandle, string name) return res; } - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlopen(String fileName, int flags); + class Linux + { + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlopen(String fileName, int flags); - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - private static extern IntPtr dlsym(IntPtr handle, String symbol); + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr dlsym(IntPtr handle, String symbol); - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern int dlclose(IntPtr handle); + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int dlclose(IntPtr handle); - [DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr dlerror(); -#else // Windows - private const string NativeDll = "kernel32.dll"; + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr dlerror(); + } - [DllImport(NativeDll)] - public static extern IntPtr LoadLibrary(string dllToLoad); + class Mac + { + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlopen(String fileName, int flags); - [DllImport(NativeDll)] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr dlsym(IntPtr handle, String symbol); - [DllImport(NativeDll)] - public static extern bool FreeLibrary(IntPtr hModule); -#endif + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int dlclose(IntPtr handle); + + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr dlerror(); + } + + // #else // Windows + private const string WinNativeDll = "kernel32.dll"; + + [DllImport(WinNativeDll, EntryPoint = "LoadLibrary")] + public static extern IntPtr WinLoadLibrary(string dllToLoad); + + [DllImport(WinNativeDll, EntryPoint = "GetProcAddress")] + public static extern IntPtr WinGetProcAddress(IntPtr hModule, string procedureName); + + [DllImport(WinNativeDll, EntryPoint = "FreeLibrary")] + public static extern bool WinFreeLibrary(IntPtr hModule); +// #endif + public static IntPtr LoadLibrary(string dllToLoad) => impl.LoadLibrary(dllToLoad); + + public static IntPtr GetProcAddress(IntPtr hModule, string procedureName) + => impl.GetProcAddress(hModule, procedureName); + + public static void FreeLibrary(IntPtr hModule) => impl.FreeLibrary(hModule); + + + static readonly NativeMethodsImpl impl = + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new NativeMethodsImpl { + LoadLibrary = WinLoadLibrary, + GetProcAddress = WinGetProcAddress, + FreeLibrary = h => WinFreeLibrary(h), + } : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? new NativeMethodsImpl { + LoadLibrary = LinuxLoadLibrary, + GetProcAddress = UnixGetProcAddress, + FreeLibrary = h => Linux.dlclose(h), + } : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? new NativeMethodsImpl { + LoadLibrary = MacLoadLibrary, + GetProcAddress = UnixGetProcAddress, + FreeLibrary = h => Mac.dlclose(h), + } : Throw(new PlatformNotSupportedException()); + + struct NativeMethodsImpl + { + public Func LoadLibrary { get; set; } + public Func GetProcAddress { get; set; } + public Action FreeLibrary { get; set; } + } + + internal static T Throw(Exception exception) + { + throw exception; + } } /// @@ -110,27 +155,8 @@ public class Runtime // We needs to replace all public constants to static readonly fields to allow // binary substitution of different Python.Runtime.dll builds in a target application. - public static int UCS => _UCS; - -#if UCS4 - internal const int _UCS = 4; - - /// - /// EntryPoint to be used in DllImport to map to correct Unicode - /// methods prior to PEP393. Only used for PY27. - /// - private const string PyUnicodeEntryPoint = "PyUnicodeUCS4_"; -#elif UCS2 - internal const int _UCS = 2; - - /// - /// EntryPoint to be used in DllImport to map to correct Unicode - /// methods prior to PEP393. Only used for PY27. - /// - private const string PyUnicodeEntryPoint = "PyUnicodeUCS2_"; -#else -#error You must define either UCS2 or UCS4! -#endif + public static int UCS { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 4; + public static string PyUnicodeEntryPoint { get; } = UCS == 2 ? "PyUnicodeUCS2_" : "PyUnicodeUCS4_"; // C# compiler copies constants to the assemblies that references this library. // We needs to replace all public constants to static readonly fields to allow @@ -266,7 +292,7 @@ public enum MachineType /// /// Encoding to use to convert Unicode to/from Managed to Native /// - internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32; + internal static readonly Encoding PyEncoding = UCS == 2 ? Encoding.Unicode : Encoding.UTF32; /// /// Initialize the runtime... @@ -1349,7 +1375,7 @@ internal static bool PyString_Check(IntPtr ob) internal static IntPtr PyString_FromString(string value) { #if PYTHON3 - return PyUnicode_FromKindAndData(_UCS, value, value.Length); + return PyUnicode_FromKindAndData(UCS, value, value.Length); #elif PYTHON2 return PyString_FromStringAndSize(value, value.Length); #endif @@ -1434,7 +1460,7 @@ IntPtr size internal static IntPtr PyUnicode_FromUnicode(string s, long size) { - return PyUnicode_FromKindAndData(_UCS, s, size); + return PyUnicode_FromKindAndData(UCS, s, size); } internal static long PyUnicode_GetSize(IntPtr ob) @@ -1523,7 +1549,7 @@ internal static string GetManagedString(IntPtr op) IntPtr p = PyUnicode_AsUnicode(op); int length = (int)PyUnicode_GetSize(op); - int size = length * _UCS; + int size = length * UCS; var buffer = new byte[size]; Marshal.Copy(p, buffer, 0, size); return PyEncoding.GetString(buffer, 0, size); @@ -2163,18 +2189,14 @@ static Delegates() RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? libraryName + ".dll" : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? $"lib{libraryName}.so" : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"lib{libraryName}.dylib" - : Throw(new PlatformNotSupportedException()); + : NativeMethods.Throw(new PlatformNotSupportedException()); } IntPtr handle = NativeMethods.LoadLibrary(libraryName); if (handle == IntPtr.Zero) - throw new FileLoadException(); + throw new FileLoadException("Could not load " + libraryName); return handle; } - static T Throw(Exception exception) { - throw exception; - } - static global::System.IntPtr GetFunctionByName(string functionName, global::System.IntPtr libraryHandle) { IntPtr functionPointer = NativeMethods.GetProcAddress(libraryHandle, functionName); if (functionPointer == IntPtr.Zero) From f77490c6bb89d271b6c072b860f5e78357ff1455 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 17:21:05 -0800 Subject: [PATCH 017/240] fixed OSX failing to load any native libraries --- src/runtime/runtime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 30244e587..45e5c8bdc 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -125,7 +125,7 @@ public static IntPtr GetProcAddress(IntPtr hModule, string procedureName) LoadLibrary = LinuxLoadLibrary, GetProcAddress = UnixGetProcAddress, FreeLibrary = h => Linux.dlclose(h), - } : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? new NativeMethodsImpl { + } : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? new NativeMethodsImpl { LoadLibrary = MacLoadLibrary, GetProcAddress = UnixGetProcAddress, FreeLibrary = h => Mac.dlclose(h), From ab31c4c9a5ee1cc085850989688b44ccbc94af5d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 14 Feb 2019 19:12:11 -0800 Subject: [PATCH 018/240] fixed crash on startup on Windows --- src/runtime/runtime.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 45e5c8bdc..6bb772be6 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -32,17 +32,17 @@ public static IntPtr MacLoadLibrary(string fileName) return Mac.dlopen(fileName, RTLD_NOW | MAC_RTLD_GLOBAL); } - static readonly IntPtr RTLD_DEFAULT = + static readonly IntPtr? RTLD_DEFAULT = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? LINUX_RTLD_DEFAULT : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MAC_RTLD_DEFAULT - : Throw(new PlatformNotSupportedException()); + : (IntPtr?)null; public static IntPtr UnixGetProcAddress(IntPtr dllHandle, string name) { // look in the exe if dllHandle is NULL if (dllHandle == IntPtr.Zero) { - dllHandle = RTLD_DEFAULT; + dllHandle = RTLD_DEFAULT.Value; } // clear previous errors if any From e9afc37d9e1ac9b04f5b61fd2b44933dbf5404fb Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 25 Feb 2019 15:01:21 -0800 Subject: [PATCH 019/240] fixed reference assembly not working in tests --- src/runtime/Python.Runtime.Ref.csproj | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/runtime/Python.Runtime.Ref.csproj b/src/runtime/Python.Runtime.Ref.csproj index 11dbc77b9..448138721 100644 --- a/src/runtime/Python.Runtime.Ref.csproj +++ b/src/runtime/Python.Runtime.Ref.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -8,6 +8,7 @@ Python.Runtime Python.Runtime True + bin\ref\ $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml false @@ -22,7 +23,7 @@ $(PYTHONNET_PY3_VERSION) PYTHON36 - $(DefineConstants);XPLAT;NETSTANDARD;UCS2;$(Python3Version);PYTHON3 + $(DefineConstants);XPLAT;NETSTANDARD;$(Python3Version);PYTHON3 @@ -31,4 +32,10 @@ + + + clr.py + + + From e3249a6b00e787b024490b9feaa2d0dca66f2955 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 25 Feb 2019 15:01:56 -0800 Subject: [PATCH 020/240] added a test for passing DLR objects to Python --- src/embed_tests/TestPassDynamic.cs | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/embed_tests/TestPassDynamic.cs diff --git a/src/embed_tests/TestPassDynamic.cs b/src/embed_tests/TestPassDynamic.cs new file mode 100644 index 000000000..bcef90f2a --- /dev/null +++ b/src/embed_tests/TestPassDynamic.cs @@ -0,0 +1,33 @@ +namespace Python.EmbeddingTest { + using System; + using System.Collections.Generic; + using System.Dynamic; + using System.Text; + using NUnit.Framework; + using Python.Runtime; + + public class TestPassDynamic { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void ExpandoProperties() { + dynamic expando = new ExpandoObject(); + expando.test = 42; + using (Py.GIL()) { + dynamic getTest = PythonEngine.Eval("lambda o: o.test"); + int read = getTest(expando); + Assert.AreEqual(42, read); + } + } + } +} From 542105a70f4bb57c9dd91dc23b1e75e2f4bdc435 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 8 Mar 2019 22:36:52 -0800 Subject: [PATCH 021/240] minor addition to .editorconfig --- .editorconfig | 3 +++ pythonnet.15.sln | 1 + 2 files changed, 4 insertions(+) diff --git a/.editorconfig b/.editorconfig index 2e7c58ffe..525ffcde1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -27,3 +27,6 @@ indent_style = tab [.bumpversion.cfg] trim_trailing_whitespace = false indent_style = tab + +[*.cs] +csharp_new_line_before_open_brace = true diff --git a/pythonnet.15.sln b/pythonnet.15.sln index cac63ec12..260b61d43 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -14,6 +14,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Test.15", "src\testi EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{B6E8FE48-C755-496E-9BE0-34A60B77CA03}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig global.json = global.json EndProjectSection EndProject From ce97c415a13ad8c1c623f7f80d58af24d2ca6056 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 8 Mar 2019 22:37:18 -0800 Subject: [PATCH 022/240] cleaned up MethodBinder.Bind a bit --- src/runtime/methodbinder.cs | 271 ++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 135 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index ef2e20700..465e2dbf7 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -283,7 +283,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth var pynargs = (int)Runtime.PyTuple_Size(args); object arg; var isGeneric = false; - ArrayList defaultArgList = null; if (info != null) { _methods = new MethodBase[1]; @@ -302,180 +301,151 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth isGeneric = true; } ParameterInfo[] pi = mi.GetParameters(); - var clrnargs = pi.Length; - var match = false; - var arrayStart = -1; - var outs = 0; + ArrayList defaultArgList; + int arrayStart; - if (pynargs == clrnargs) - { - match = true; + if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + continue; } - else if (pynargs < clrnargs) + var outs = 0; + var margs = new object[pi.Length]; + + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) { - match = true; - defaultArgList = new ArrayList(); - for (var v = pynargs; v < clrnargs; v++) + IntPtr op; + if (paramIndex >= pynargs) { - if (pi[v].DefaultValue == DBNull.Value) + if (defaultArgList != null) { - match = false; - } - else - { - defaultArgList.Add(pi[v].DefaultValue); + margs[paramIndex] = defaultArgList[paramIndex - pynargs]; } + + continue; } - } - else if (pynargs > clrnargs && clrnargs > 0 && - Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute))) - { - // This is a `foo(params object[] bar)` style method - match = true; - arrayStart = clrnargs - 1; - } - if (match) - { - var margs = new object[clrnargs]; + if (arrayStart == paramIndex) + { + // map remaining Python arguments to a tuple since + // the managed function accepts it - hopefully :] + op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); + } + else + { + op = Runtime.PyTuple_GetItem(args, paramIndex); + } - for (int n = 0; n < clrnargs; n++) + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + clrtype = null; + IntPtr pyoptype; + if (_methods.Length > 1) { - IntPtr op; - if (n < pynargs) + pyoptype = IntPtr.Zero; + pyoptype = Runtime.PyObject_Type(op); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) { - if (arrayStart == n) - { - // map remaining Python arguments to a tuple since - // the managed function accepts it - hopefully :] - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); - } - else - { - op = Runtime.PyTuple_GetItem(args, n); - } - - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - clrtype = null; - IntPtr pyoptype; - if (_methods.Length > 1) - { - pyoptype = IntPtr.Zero; - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - clrtype = Converter.GetTypeByAlias(pyoptype); - } - Runtime.XDecref(pyoptype); - } + clrtype = Converter.GetTypeByAlias(pyoptype); + } + Runtime.XDecref(pyoptype); + } - if (clrtype != null) + if (clrtype != null) + { + var typematch = false; + if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype)) + { + IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType); + pyoptype = Runtime.PyObject_Type(op); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) { - var typematch = false; - if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype)) + if (pytype != pyoptype) { - IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - if (pytype != pyoptype) - { - typematch = false; - } - else - { - typematch = true; - clrtype = pi[n].ParameterType; - } - } - if (!typematch) - { - // this takes care of enum values - TypeCode argtypecode = Type.GetTypeCode(pi[n].ParameterType); - TypeCode paramtypecode = Type.GetTypeCode(clrtype); - if (argtypecode == paramtypecode) - { - typematch = true; - clrtype = pi[n].ParameterType; - } - } - Runtime.XDecref(pyoptype); - if (!typematch) - { - margs = null; - break; - } + typematch = false; } else { typematch = true; - clrtype = pi[n].ParameterType; + clrtype = pi[paramIndex].ParameterType; } } - else + if (!typematch) { - clrtype = pi[n].ParameterType; - } - - if (pi[n].IsOut || clrtype.IsByRef) - { - outs++; + // this takes care of enum values + TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType); + TypeCode paramtypecode = Type.GetTypeCode(clrtype); + if (argtypecode == paramtypecode) + { + typematch = true; + clrtype = pi[paramIndex].ParameterType; + } } - - if (!Converter.ToManaged(op, clrtype, out arg, false)) + Runtime.XDecref(pyoptype); + if (!typematch) { - Exceptions.Clear(); margs = null; break; } - if (arrayStart == n) - { - // GetSlice() creates a new reference but GetItem() - // returns only a borrow reference. - Runtime.XDecref(op); - } - margs[n] = arg; } else { - if (defaultArgList != null) - { - margs[n] = defaultArgList[n - pynargs]; - } + typematch = true; + clrtype = pi[paramIndex].ParameterType; } } + else + { + clrtype = pi[paramIndex].ParameterType; + } - if (margs == null) + if (pi[paramIndex].IsOut || clrtype.IsByRef) { - continue; + outs++; } - object target = null; - if (!mi.IsStatic && inst != IntPtr.Zero) + if (!Converter.ToManaged(op, clrtype, out arg, false)) { - //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); - // InvalidCastException: Unable to cast object of type - // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' - var co = ManagedType.GetManagedObject(inst) as CLRObject; - - // Sanity check: this ensures a graceful exit if someone does - // something intentionally wrong like call a non-static method - // on the class rather than on an instance of the class. - // XXX maybe better to do this before all the other rigmarole. - if (co == null) - { - return null; - } - target = co.inst; + Exceptions.Clear(); + margs = null; + break; } + if (arrayStart == paramIndex) + { + // GetSlice() creates a new reference but GetItem() + // returns only a borrow reference. + Runtime.XDecref(op); + } + margs[paramIndex] = arg; + } - return new Binding(mi, target, margs, outs); + if (margs == null) + { + continue; } + + object target = null; + if (!mi.IsStatic && inst != IntPtr.Zero) + { + //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst); + // InvalidCastException: Unable to cast object of type + // 'Python.Runtime.ClassObject' to type 'Python.Runtime.CLRObject' + var co = ManagedType.GetManagedObject(inst) as CLRObject; + + // Sanity check: this ensures a graceful exit if someone does + // something intentionally wrong like call a non-static method + // on the class rather than on an instance of the class. + // XXX maybe better to do this before all the other rigmarole. + if (co == null) + { + return null; + } + target = co.inst; + } + + return new Binding(mi, target, margs, outs); } // We weren't able to find a matching method but at least one // is a generic method and info is null. That happens when a generic @@ -490,6 +460,37 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList) + { + defaultArgList = null; + var match = false; + paramsArrayStart = -1; + + if (pynargs == pi.Length) + { + match = true; + } else if (pynargs < pi.Length) + { + match = true; + defaultArgList = new ArrayList(); + for (var v = pynargs; v < pi.Length; v++) { + if (pi[v].DefaultValue == DBNull.Value) { + match = false; + } else { + defaultArgList.Add(pi[v].DefaultValue); + } + } + } else if (pynargs > pi.Length && pi.Length > 0 && + Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute))) + { + // This is a `foo(params object[] bar)` style method + match = true; + paramsArrayStart = pi.Length - 1; + } + + return match; + } + internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw) { return Invoke(inst, args, kw, null, null); From 99be001b09c34fd881f1f182ea64108f18a5f725 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 9 Mar 2019 00:42:55 -0800 Subject: [PATCH 023/240] a bit more refactoring of MethodBinder.Bind --- src/runtime/methodbinder.cs | 177 +++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 465e2dbf7..1ca57ac22 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -292,7 +292,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth { _methods = GetMethods(); } - Type clrtype; + // TODO: Clean up foreach (MethodBase mi in _methods) { @@ -304,7 +304,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth ArrayList defaultArgList; int arrayStart; - if (!MatchArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + if (!MatchesArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { continue; } var outs = 0; @@ -312,7 +312,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) { - IntPtr op; if (paramIndex >= pynargs) { if (defaultArgList != null) @@ -323,85 +322,21 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; } - if (arrayStart == paramIndex) - { + IntPtr op = (arrayStart == paramIndex) // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] - op = Runtime.PyTuple_GetSlice(args, arrayStart, pynargs); - } - else - { - op = Runtime.PyTuple_GetItem(args, paramIndex); - } - - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - clrtype = null; - IntPtr pyoptype; - if (_methods.Length > 1) - { - pyoptype = IntPtr.Zero; - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - clrtype = Converter.GetTypeByAlias(pyoptype); - } - Runtime.XDecref(pyoptype); - } + ? Runtime.PyTuple_GetSlice(args, arrayStart, pynargs) + : Runtime.PyTuple_GetItem(args, paramIndex); + var parameter = pi[paramIndex]; - if (clrtype != null) - { - var typematch = false; - if ((pi[paramIndex].ParameterType != typeof(object)) && (pi[paramIndex].ParameterType != clrtype)) - { - IntPtr pytype = Converter.GetPythonTypeByAlias(pi[paramIndex].ParameterType); - pyoptype = Runtime.PyObject_Type(op); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - if (pytype != pyoptype) - { - typematch = false; - } - else - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - if (!typematch) - { - // this takes care of enum values - TypeCode argtypecode = Type.GetTypeCode(pi[paramIndex].ParameterType); - TypeCode paramtypecode = Type.GetTypeCode(clrtype); - if (argtypecode == paramtypecode) - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - Runtime.XDecref(pyoptype); - if (!typematch) - { - margs = null; - break; - } - } - else - { - typematch = true; - clrtype = pi[paramIndex].ParameterType; - } - } - else - { - clrtype = pi[paramIndex].ParameterType; + var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: _methods.Length > 1); + if (clrtype == null) { + margs = null; + break; } - if (pi[paramIndex].IsOut || clrtype.IsByRef) + if (parameter.IsOut || clrtype.IsByRef) { outs++; } @@ -460,32 +395,104 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } - static bool MatchArgumentCount(int pynargs, ParameterInfo[] pi, out int paramsArrayStart, out ArrayList defaultArgList) + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) + { + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + Type clrtype = null; + IntPtr pyoptype; + if (needsResolution) + { + // HACK: each overload should be weighted in some way instead + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) + { + clrtype = Converter.GetTypeByAlias(pyoptype); + } + Runtime.XDecref(pyoptype); + } + + if (clrtype != null) + { + var typematch = false; + if ((parameterType != typeof(object)) && (parameterType != clrtype)) + { + IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType); + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) + { + if (pytype != pyoptype) + { + typematch = false; + } + else + { + typematch = true; + clrtype = parameterType; + } + } + if (!typematch) + { + // this takes care of enum values + TypeCode argtypecode = Type.GetTypeCode(parameterType); + TypeCode paramtypecode = Type.GetTypeCode(clrtype); + if (argtypecode == paramtypecode) + { + typematch = true; + clrtype = parameterType; + } + } + Runtime.XDecref(pyoptype); + if (!typematch) + { + return null; + } + } + else + { + typematch = true; + clrtype = parameterType; + } + } + else + { + clrtype = parameterType; + } + + return clrtype; + } + + static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, + out int paramsArrayStart, + out ArrayList defaultArgList) { defaultArgList = null; var match = false; paramsArrayStart = -1; - if (pynargs == pi.Length) + if (argumentCount == parameters.Length) { match = true; - } else if (pynargs < pi.Length) + } else if (argumentCount < parameters.Length) { match = true; defaultArgList = new ArrayList(); - for (var v = pynargs; v < pi.Length; v++) { - if (pi[v].DefaultValue == DBNull.Value) { + for (var v = argumentCount; v < parameters.Length; v++) { + if (parameters[v].DefaultValue == DBNull.Value) { match = false; } else { - defaultArgList.Add(pi[v].DefaultValue); + defaultArgList.Add(parameters[v].DefaultValue); } } - } else if (pynargs > pi.Length && pi.Length > 0 && - Attribute.IsDefined(pi[pi.Length - 1], typeof(ParamArrayAttribute))) + } else if (argumentCount > parameters.Length && parameters.Length > 0 && + Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute))) { // This is a `foo(params object[] bar)` style method match = true; - paramsArrayStart = pi.Length - 1; + paramsArrayStart = parameters.Length - 1; } return match; From 1d35499d80c648c43c40722fc47a57b4cd6344de Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:00:06 -0700 Subject: [PATCH 024/240] extracted TryConvertArguments from MethodBinder.Bind --- src/runtime/methodbinder.cs | 120 ++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 1ca57ac22..9bc4c3646 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -281,7 +281,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth // loop to find match, return invoker w/ or /wo error MethodBase[] _methods = null; var pynargs = (int)Runtime.PyTuple_Size(args); - object arg; var isGeneric = false; if (info != null) { @@ -302,59 +301,15 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth } ParameterInfo[] pi = mi.GetParameters(); ArrayList defaultArgList; - int arrayStart; + bool paramsArray; - if (!MatchesArgumentCount(pynargs, pi, out arrayStart, out defaultArgList)) { + if (!MatchesArgumentCount(pynargs, pi, out paramsArray, out defaultArgList)) { continue; } var outs = 0; - var margs = new object[pi.Length]; - - for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) - { - if (paramIndex >= pynargs) - { - if (defaultArgList != null) - { - margs[paramIndex] = defaultArgList[paramIndex - pynargs]; - } - - continue; - } - - IntPtr op = (arrayStart == paramIndex) - // map remaining Python arguments to a tuple since - // the managed function accepts it - hopefully :] - ? Runtime.PyTuple_GetSlice(args, arrayStart, pynargs) - : Runtime.PyTuple_GetItem(args, paramIndex); - - var parameter = pi[paramIndex]; - - var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: _methods.Length > 1); - if (clrtype == null) { - margs = null; - break; - } - - if (parameter.IsOut || clrtype.IsByRef) - { - outs++; - } - - if (!Converter.ToManaged(op, clrtype, out arg, false)) - { - Exceptions.Clear(); - margs = null; - break; - } - if (arrayStart == paramIndex) - { - // GetSlice() creates a new reference but GetItem() - // returns only a borrow reference. - Runtime.XDecref(op); - } - margs[paramIndex] = arg; - } + var margs = TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList, + needsResolution: _methods.Length > 1, + outs: out outs); if (margs == null) { @@ -395,6 +350,65 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, + IntPtr args, int pyArgCount, + ArrayList defaultArgList, + bool needsResolution, + out int outs) + { + outs = 0; + var margs = new object[pi.Length]; + int arrayStart = paramsArray ? pi.Length - 1 : -1; + + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) + { + if (paramIndex >= pyArgCount) + { + if (defaultArgList != null) + { + margs[paramIndex] = defaultArgList[paramIndex - pyArgCount]; + } + + continue; + } + + IntPtr op = (arrayStart == paramIndex) + // map remaining Python arguments to a tuple since + // the managed function accepts it - hopefully :] + ? Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount) + : Runtime.PyTuple_GetItem(args, paramIndex); + + var parameter = pi[paramIndex]; + + var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: needsResolution); + if (clrtype == null) + { + return null; + } + + if (parameter.IsOut || clrtype.IsByRef) + { + outs++; + } + + object arg; + if (!Converter.ToManaged(op, clrtype, out arg, false)) + { + Exceptions.Clear(); + return null; + } + if (arrayStart == paramIndex) + { + // GetSlice() creates a new reference but GetItem() + // returns only a borrow reference. + Runtime.XDecref(op); + } + margs[paramIndex] = arg; + } + + return margs; + } + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) { // this logic below handles cases when multiple overloading methods @@ -466,12 +480,12 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool } static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, - out int paramsArrayStart, + out bool paramsArray, out ArrayList defaultArgList) { defaultArgList = null; var match = false; - paramsArrayStart = -1; + paramsArray = false; if (argumentCount == parameters.Length) { @@ -492,7 +506,7 @@ static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, { // This is a `foo(params object[] bar)` style method match = true; - paramsArrayStart = parameters.Length - 1; + paramsArray = true; } return match; From 2368837414eb2fe0c5c2e66242c2f5065e186365 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:35:10 -0700 Subject: [PATCH 025/240] extracted TryConvertArgument from MethodBinder.TryConvertArguments --- src/runtime/methodbinder.cs | 46 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 9bc4c3646..52cfd4eb5 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -372,43 +372,57 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, continue; } + var parameter = pi[paramIndex]; IntPtr op = (arrayStart == paramIndex) // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] ? Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount) : Runtime.PyTuple_GetItem(args, paramIndex); - var parameter = pi[paramIndex]; - - var clrtype = TryComputeClrArgumentType(parameter.ParameterType, op, needsResolution: needsResolution); - if (clrtype == null) + bool isOut; + if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { return null; } - if (parameter.IsOut || clrtype.IsByRef) - { - outs++; - } - - object arg; - if (!Converter.ToManaged(op, clrtype, out arg, false)) - { - Exceptions.Clear(); - return null; - } if (arrayStart == paramIndex) { + // TODO: is this a bug? Should this happen even if the conversion fails? // GetSlice() creates a new reference but GetItem() // returns only a borrow reference. Runtime.XDecref(op); } - margs[paramIndex] = arg; + + if (parameter.IsOut || isOut) + { + outs++; + } } return margs; } + static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, + out object arg, out bool isOut) + { + arg = null; + isOut = false; + var clrtype = TryComputeClrArgumentType(parameterType, op, needsResolution: needsResolution); + if (clrtype == null) + { + return false; + } + + if (!Converter.ToManaged(op, clrtype, out arg, false)) + { + Exceptions.Clear(); + return false; + } + + isOut = clrtype.IsByRef; + return true; + } + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) { // this logic below handles cases when multiple overloading methods From e52284a1b3d333277082ae2cac684897e6f043ce Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 10 Mar 2019 16:42:10 -0700 Subject: [PATCH 026/240] added a documentation comment for MethodBinder.TryConvertArguments --- src/runtime/methodbinder.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 52cfd4eb5..95b953555 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -350,6 +350,18 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth return null; } + /// + /// Attempts to convert Python argument tuple into an array of managed objects, + /// that can be passed to a method. + /// + /// Information about expected parameters + /// true, if the last parameter is a params array. + /// A pointer to the Python argument tuple + /// Number of arguments, passed by Python + /// A list of default values for omitted parameters + /// true, if overloading resolution is required + /// Returns number of output parameters + /// An array of .NET arguments, that can be passed to a method. static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, IntPtr args, int pyArgCount, ArrayList defaultArgList, From 611e9c077487e48cd91e960f183aa4917995bcb2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 Mar 2019 14:26:38 -0700 Subject: [PATCH 027/240] drop net40 target --- src/console/Console.15.csproj | 2 +- src/embed_tests/Python.EmbeddingTest.15.csproj | 4 ++-- src/testing/Python.Test.15.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/console/Console.15.csproj b/src/console/Console.15.csproj index ec5008036..dc8fc72c1 100644 --- a/src/console/Console.15.csproj +++ b/src/console/Console.15.csproj @@ -1,7 +1,7 @@ - net40;netcoreapp2.0 + netcoreapp2.0 x64;x86 DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Exe diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index a741a589e..b8aa57a61 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -2,7 +2,7 @@ - net40;netcoreapp2.0 + netcoreapp2.0 x64;x86 DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Exe @@ -86,7 +86,7 @@ - + diff --git a/src/testing/Python.Test.15.csproj b/src/testing/Python.Test.15.csproj index da20ed2ef..79387ce7f 100644 --- a/src/testing/Python.Test.15.csproj +++ b/src/testing/Python.Test.15.csproj @@ -1,7 +1,7 @@ - net40;netstandard2.0 + netstandard2.0 x64;x86 DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Python.Test From 9d58a72cf501446ac7869ae0c44a345138855c92 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 Mar 2019 14:26:59 -0700 Subject: [PATCH 028/240] remove unused code --- src/embed_tests/TestCallbacks.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index 99db401ae..157a34226 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -7,7 +7,6 @@ namespace Python.EmbeddingTest { public class TestCallbacks { [OneTimeSetUp] public void SetUp() { - string path = Environment.GetEnvironmentVariable("PATH"); } [OneTimeTearDown] From 08e33569a48cc8a7c04e1bbc72d156a4b8914644 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 28 Mar 2019 13:10:23 -0700 Subject: [PATCH 029/240] introduced IPyArgumentConverter interface, that controls marshaling of Python objects when calling .NET methods --- src/runtime/methodbinder.cs | 11 +++++--- src/runtime/pyargconverter.cs | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/runtime/pyargconverter.cs diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 95b953555..a36b2047b 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -17,6 +17,7 @@ internal class MethodBinder public MethodBase[] methods; public bool init = false; public bool allow_threads = true; + readonly IPyArgumentConverter pyArgumentConverter = DefaultPyArgumentConverter.Instance; internal MethodBinder() { @@ -307,7 +308,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; } var outs = 0; - var margs = TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList, + var margs = this.TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList, needsResolution: _methods.Length > 1, outs: out outs); @@ -362,7 +363,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth /// true, if overloading resolution is required /// Returns number of output parameters /// An array of .NET arguments, that can be passed to a method. - static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, + object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, IntPtr args, int pyArgCount, ArrayList defaultArgList, bool needsResolution, @@ -392,7 +393,9 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, : Runtime.PyTuple_GetItem(args, paramIndex); bool isOut; - if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) + if (!this.pyArgumentConverter.TryConvertArgument( + op, parameter.ParameterType, needsResolution, + out margs[paramIndex], out isOut)) { return null; } @@ -414,7 +417,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, return margs; } - static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, + internal static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, out object arg, out bool isOut) { arg = null; diff --git a/src/runtime/pyargconverter.cs b/src/runtime/pyargconverter.cs new file mode 100644 index 000000000..16d8ed551 --- /dev/null +++ b/src/runtime/pyargconverter.cs @@ -0,0 +1,47 @@ +namespace Python.Runtime { + using System; + + /// + /// Specifies how to convert Python objects, passed to .NET functions to the expected CLR types. + /// + public interface IPyArgumentConverter + { + /// + /// Attempts to convert an argument passed by Python to the specified parameter type. + /// + /// Unmanaged pointer to the Python argument value + /// The expected type of the parameter + /// true if the method is overloaded + /// This parameter will receive the converted value, matching the specified type + /// This parameter will be set to true, + /// if the final type needs to be marshaled as an out argument. + /// true, if the object matches requested type, + /// and conversion was successful, otherwise false + bool TryConvertArgument(IntPtr pyarg, Type parameterType, + bool needsResolution, out object arg, out bool isOut); + } + + public class DefaultPyArgumentConverter: IPyArgumentConverter { + public static DefaultPyArgumentConverter Instance { get; }= new DefaultPyArgumentConverter(); + + /// + /// Attempts to convert an argument passed by Python to the specified parameter type. + /// + /// Unmanaged pointer to the Python argument value + /// The expected type of the parameter + /// true if the method is overloaded + /// This parameter will receive the converted value, matching the specified type + /// This parameter will be set to true, + /// if the final type needs to be marshaled as an out argument. + /// true, if the object matches requested type, + /// and conversion was successful, otherwise false + public virtual bool TryConvertArgument( + IntPtr pyarg, Type parameterType, bool needsResolution, + out object arg, out bool isOut) + { + return MethodBinder.TryConvertArgument( + pyarg, parameterType, needsResolution, + out arg, out isOut); + } + } +} From 8d069cc8ef59fdeb960af14ab163211f99bb2d12 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 28 Mar 2019 15:52:38 -0700 Subject: [PATCH 030/240] enabled an ability to override Python to .NET argument coversion using PyArgConverter attribute --- src/embed_tests/TestCustomArgMarshal.cs | 53 +++++++++++++++++++++++++ src/runtime/methodbinder.cs | 31 +++++++++++++-- src/runtime/pyargconverter.cs | 44 +++++++++++++++++++- 3 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 src/embed_tests/TestCustomArgMarshal.cs diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs new file mode 100644 index 000000000..9bb8ae7f3 --- /dev/null +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -0,0 +1,53 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + class TestCustomArgMarshal + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void CustomArgMarshaller() + { + var obj = new CustomArgMarshaling(); + using (Py.GIL()) { + dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallWithInt('42')"); + callWithInt(obj.ToPython()); + } + Assert.AreEqual(expected: 42, actual: obj.LastArgument); + } + } + + [PyArgConverter(typeof(CustomArgConverter))] + class CustomArgMarshaling { + public object LastArgument { get; private set; } + public void CallWithInt(int value) => this.LastArgument = value; + } + + class CustomArgConverter : DefaultPyArgumentConverter { + public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, + out object arg, out bool isOut) { + if (parameterType != typeof(int)) + return base.TryConvertArgument(pyarg, parameterType, needsResolution, out arg, out isOut); + bool isString = base.TryConvertArgument(pyarg, typeof(string), needsResolution, + out arg, out isOut); + if (!isString) return false; + int number; + if (!int.TryParse((string)arg, out number)) return false; + arg = number; + return true; + } + } +} diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index a36b2047b..e0206d59f 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Diagnostics; using System.Reflection; using System.Text; @@ -17,16 +18,16 @@ internal class MethodBinder public MethodBase[] methods; public bool init = false; public bool allow_threads = true; - readonly IPyArgumentConverter pyArgumentConverter = DefaultPyArgumentConverter.Instance; + IPyArgumentConverter pyArgumentConverter; internal MethodBinder() { list = new ArrayList(); } - internal MethodBinder(MethodInfo mi) + internal MethodBinder(MethodInfo mi): this() { - list = new ArrayList { mi }; + this.AddMethod(mi); } public int Count @@ -36,6 +37,7 @@ public int Count internal void AddMethod(MethodBase m) { + Debug.Assert(!init); list.Add(m); } @@ -163,11 +165,34 @@ internal MethodBase[] GetMethods() // I'm sure this could be made more efficient. list.Sort(new MethodSorter()); methods = (MethodBase[])list.ToArray(typeof(MethodBase)); + pyArgumentConverter = this.GetArgumentConverter(); init = true; } return methods; } + IPyArgumentConverter GetArgumentConverter() { + IPyArgumentConverter converter = null; + Type converterType = null; + foreach (MethodBase method in this.methods) + { + var attribute = method.DeclaringType?.GetCustomAttribute() + ?? method.DeclaringType?.Assembly.GetCustomAttribute(); + if (converterType == null) + { + if (attribute == null) continue; + + converterType = attribute.ConverterType; + converter = attribute.Converter; + } else if (converterType != attribute?.ConverterType) + { + throw new NotSupportedException("All methods must have the same IPyArgumentConverter"); + } + } + + return converter ?? DefaultPyArgumentConverter.Instance; + } + /// /// Precedence algorithm largely lifted from Jython - the concerns are /// generally the same so we'll start with this and tweak as necessary. diff --git a/src/runtime/pyargconverter.cs b/src/runtime/pyargconverter.cs index 16d8ed551..69dfc714f 100644 --- a/src/runtime/pyargconverter.cs +++ b/src/runtime/pyargconverter.cs @@ -21,8 +21,14 @@ bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, out object arg, out bool isOut); } + /// + /// The implementation of used by default + /// public class DefaultPyArgumentConverter: IPyArgumentConverter { - public static DefaultPyArgumentConverter Instance { get; }= new DefaultPyArgumentConverter(); + /// + /// Gets the singleton instance. + /// + public static DefaultPyArgumentConverter Instance { get; } = new DefaultPyArgumentConverter(); /// /// Attempts to convert an argument passed by Python to the specified parameter type. @@ -44,4 +50,40 @@ public virtual bool TryConvertArgument( out arg, out isOut); } } + + /// + /// Specifies an argument converter to be used, when methods in this class/assembly are called from Python. + /// + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct)] + public class PyArgConverterAttribute : Attribute + { + static readonly Type[] EmptyArgTypeList = new Type[0]; + static readonly object[] EmptyArgList = new object[0]; + + /// + /// Gets the instance of the converter, that will be used when calling methods + /// of this class/assembly from Python + /// + public IPyArgumentConverter Converter { get; } + /// + /// Gets the type of the converter, that will be used when calling methods + /// of this class/assembly from Python + /// + public Type ConverterType { get; } + + /// + /// Specifies an argument converter to be used, when methods + /// in this class/assembly are called from Python. + /// + /// Type of the converter to use. + /// Must implement . + public PyArgConverterAttribute(Type converterType) + { + if (converterType == null) throw new ArgumentNullException(nameof(converterType)); + var ctor = converterType.GetConstructor(EmptyArgTypeList); + if (ctor == null) throw new ArgumentException("Specified converter must have public parameterless constructor"); + this.Converter = (IPyArgumentConverter)ctor.Invoke(EmptyArgList); + this.ConverterType = converterType; + } + } } From 34f960570e46ffe3f9a8dbe1ef65e46ad8798771 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 29 Mar 2019 13:12:54 -0700 Subject: [PATCH 031/240] enable building a separate binary for net40 target --- src/runtime/Python.Runtime.15.csproj | 5 +- src/runtime/methodbinder.cs | 17 + src/runtime/runtime.cs | 448 ++++++++++++++------------- 3 files changed, 252 insertions(+), 218 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index ee81caa03..2f9fb2cdd 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,7 +1,7 @@ - netstandard2.0 - true + netstandard2.0;net40 + true unix;win AnyCPU Debug3;Release3;DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 @@ -28,6 +28,7 @@ $(PYTHONNET_DEFINE_CONSTANTS) XPLAT $(DefineConstants);$(CustomDefineConstants);$(BaseDefineConstants); + $(DefineConstants);NETFX $(DefineConstants);NETSTANDARD $(DefineConstants);TRACE;DEBUG $(PYTHONNET_PY2_VERSION) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index e0206d59f..c970c7e82 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Text; @@ -750,4 +751,20 @@ internal Binding(MethodBase info, object inst, object[] args, int outs) this.outs = outs; } } + +#if NETFX + static class ReflectionExtensions { + public static T GetCustomAttribute(this Type type) { + return type.GetCustomAttributes(typeof(T), inherit: false) + .Cast() + .SingleOrDefault(); + } + + public static T GetCustomAttribute(this Assembly assembly) { + return assembly.GetCustomAttributes(typeof(T), inherit: false) + .Cast() + .SingleOrDefault(); + } + } +#endif } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 6bb772be6..4b7025e23 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1965,222 +1965,230 @@ public static class Delegates { static Delegates() { - Py_IncRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(PythonDLL))); - Py_DecRef = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(PythonDLL))); - Py_Initialize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(PythonDLL))); - Py_InitializeEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(PythonDLL))); - Py_IsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(PythonDLL))); - Py_Finalize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(PythonDLL))); - Py_NewInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(PythonDLL))); - Py_EndInterpreter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(PythonDLL))); - PyThreadState_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(PythonDLL))); - PyThreadState_Get = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(PythonDLL))); - PyThread_get_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(PythonDLL))); - PyThread_get_thread_ident = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(PythonDLL))); - PyThread_set_key_value = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(PythonDLL))); - PyThreadState_Swap = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(PythonDLL))); - PyGILState_Ensure = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(PythonDLL))); - PyGILState_Release = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(PythonDLL))); - PyGILState_GetThisThreadState = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(PythonDLL))); - Py_Main = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(PythonDLL))); - PyEval_InitThreads = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(PythonDLL))); - PyEval_ThreadsInitialized = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(PythonDLL))); - PyEval_AcquireLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(PythonDLL))); - PyEval_ReleaseLock = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(PythonDLL))); - PyEval_AcquireThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(PythonDLL))); - PyEval_ReleaseThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(PythonDLL))); - PyEval_SaveThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(PythonDLL))); - PyEval_RestoreThread = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(PythonDLL))); - PyEval_GetBuiltins = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(PythonDLL))); - PyEval_GetGlobals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(PythonDLL))); - PyEval_GetLocals = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(PythonDLL))); - Py_GetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(PythonDLL))); - Py_SetProgramName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(PythonDLL))); - Py_GetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(PythonDLL))); - Py_SetPythonHome = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(PythonDLL))); - Py_GetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(PythonDLL))); - Py_SetPath = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(PythonDLL))); - Py_GetVersion = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(PythonDLL))); - Py_GetPlatform = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(PythonDLL))); - Py_GetCopyright = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(PythonDLL))); - Py_GetCompiler = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(PythonDLL))); - Py_GetBuildInfo = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(PythonDLL))); - PyRun_SimpleString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_SimpleString), GetUnmanagedDll(PythonDLL))); - PyRun_String = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_String), GetUnmanagedDll(PythonDLL))); - PyEval_EvalCode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(PythonDLL))); - Py_CompileString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_CompileString), GetUnmanagedDll(PythonDLL))); - PyImport_ExecCodeModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(PythonDLL))); - PyCFunction_NewEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(PythonDLL))); - PyCFunction_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(PythonDLL))); - PyObject_HasAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(PythonDLL))); - PyObject_GetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(PythonDLL))); - PyObject_SetAttrString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(PythonDLL))); - PyObject_HasAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(PythonDLL))); - PyObject_GetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(PythonDLL))); - PyObject_SetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(PythonDLL))); - PyObject_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(PythonDLL))); - PyObject_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(PythonDLL))); - PyObject_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(PythonDLL))); - PyObject_GetIter = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(PythonDLL))); - PyObject_Call = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(PythonDLL))); - PyObject_CallObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(PythonDLL))); - PyObject_RichCompareBool = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(PythonDLL))); - PyObject_IsInstance = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(PythonDLL))); - PyObject_IsSubclass = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(PythonDLL))); - PyCallable_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(PythonDLL))); - PyObject_IsTrue = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(PythonDLL))); - PyObject_Not = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(PythonDLL))); - _PyObject_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_SizeDelegate>(GetFunctionByName("PyObject_Size", GetUnmanagedDll(PythonDLL))); - PyObject_Hash = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(PythonDLL))); - PyObject_Repr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(PythonDLL))); - PyObject_Str = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(PythonDLL))); - PyObject_Unicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyObject_Str", GetUnmanagedDll(PythonDLL))); - PyObject_Dir = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(PythonDLL))); - PyNumber_Int = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_Long", GetUnmanagedDll(PythonDLL))); - PyNumber_Long = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(PythonDLL))); - PyNumber_Float = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(PythonDLL))); - PyNumber_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(PythonDLL))); - PyInt_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(PythonDLL))); - PyInt_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(PythonDLL))); - PyInt_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(PythonDLL))); - PyLong_FromLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(PythonDLL))); - PyLong_FromUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(PythonDLL))); - PyLong_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(PythonDLL))); - PyLong_FromLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(PythonDLL))); - PyLong_FromUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(PythonDLL))); - PyLong_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(PythonDLL))); - PyLong_AsLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(PythonDLL))); - PyLong_AsUnsignedLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLong), GetUnmanagedDll(PythonDLL))); - PyLong_AsLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(PythonDLL))); - PyLong_AsUnsignedLongLong = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(PythonDLL))); - PyFloat_FromDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(PythonDLL))); - PyFloat_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(PythonDLL))); - PyFloat_AsDouble = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(PythonDLL))); - PyNumber_Add = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(PythonDLL))); - PyNumber_Subtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(PythonDLL))); - PyNumber_Multiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(PythonDLL))); - PyNumber_Divide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_TrueDivide", GetUnmanagedDll(PythonDLL))); - PyNumber_And = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(PythonDLL))); - PyNumber_Xor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(PythonDLL))); - PyNumber_Or = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(PythonDLL))); - PyNumber_Lshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(PythonDLL))); - PyNumber_Rshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(PythonDLL))); - PyNumber_Power = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(PythonDLL))); - PyNumber_Remainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceAdd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceSubtract = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceMultiply = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceDivide = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_InPlaceTrueDivide", GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceAnd = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceXor = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceOr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceLshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceRshift = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlacePower = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(PythonDLL))); - PyNumber_InPlaceRemainder = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(PythonDLL))); - PyNumber_Negative = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(PythonDLL))); - PyNumber_Positive = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(PythonDLL))); - PyNumber_Invert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(PythonDLL))); - PySequence_Check = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(PythonDLL))); - PySequence_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(PythonDLL))); - PySequence_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(PythonDLL))); - PySequence_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(PythonDLL))); - PySequence_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(PythonDLL))); - PySequence_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(PythonDLL))); - PySequence_DelSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(PythonDLL))); - _PySequence_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_SizeDelegate>(GetFunctionByName("PySequence_Size", GetUnmanagedDll(PythonDLL))); - PySequence_Contains = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(PythonDLL))); - PySequence_Concat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(PythonDLL))); - PySequence_Repeat = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(PythonDLL))); - PySequence_Index = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(PythonDLL))); - _PySequence_Count = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PySequence_CountDelegate>(GetFunctionByName("PySequence_Count", GetUnmanagedDll(PythonDLL))); - PySequence_Tuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(PythonDLL))); - PySequence_List = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(PythonDLL))); - PyBytes_FromString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(PythonDLL))); - _PyBytes_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyBytes_SizeDelegate>(GetFunctionByName("PyBytes_Size", GetUnmanagedDll(PythonDLL))); - _PyString_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyString_FromStringAndSizeDelegate>(GetFunctionByName("PyUnicode_FromStringAndSize", GetUnmanagedDll(PythonDLL))); - PyUnicode_FromStringAndSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(PythonDLL))); - PyUnicode_FromObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(PythonDLL))); - PyUnicode_FromEncodedObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(PythonDLL))); - PyUnicode_FromKindAndData = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(PythonDLL))); - _PyUnicode_GetSize = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyUnicode_GetSizeDelegate>(GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(PythonDLL))); - PyUnicode_AsUnicode = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(PythonDLL))); - PyUnicode_FromOrdinal = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(PythonDLL))); - PyDict_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(PythonDLL))); - PyDictProxy_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(PythonDLL))); - PyDict_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(PythonDLL))); - PyDict_GetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(PythonDLL))); - PyDict_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(PythonDLL))); - PyDict_SetItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(PythonDLL))); - PyDict_DelItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(PythonDLL))); - PyDict_DelItemString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(PythonDLL))); - PyMapping_HasKey = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(PythonDLL))); - PyDict_Keys = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(PythonDLL))); - PyDict_Values = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(PythonDLL))); - PyDict_Items = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(PythonDLL))); - PyDict_Copy = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(PythonDLL))); - PyDict_Update = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(PythonDLL))); - PyDict_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(PythonDLL))); - _PyDict_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyDict_SizeDelegate>(GetFunctionByName("PyDict_Size", GetUnmanagedDll(PythonDLL))); - PyList_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(PythonDLL))); - PyList_AsTuple = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(PythonDLL))); - PyList_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(PythonDLL))); - PyList_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(PythonDLL))); - PyList_Insert = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(PythonDLL))); - PyList_Append = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(PythonDLL))); - PyList_Reverse = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(PythonDLL))); - PyList_Sort = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(PythonDLL))); - PyList_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(PythonDLL))); - PyList_SetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(PythonDLL))); - _PyList_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyList_SizeDelegate>(GetFunctionByName("PyList_Size", GetUnmanagedDll(PythonDLL))); - PyTuple_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(PythonDLL))); - PyTuple_GetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(PythonDLL))); - PyTuple_SetItem = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(PythonDLL))); - PyTuple_GetSlice = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(PythonDLL))); - _PyTuple_Size = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyTuple_SizeDelegate>(GetFunctionByName("PyTuple_Size", GetUnmanagedDll(PythonDLL))); - PyIter_Next = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(PythonDLL))); - PyModule_New = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(PythonDLL))); - PyModule_GetName = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(PythonDLL))); - PyModule_GetDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(PythonDLL))); - PyModule_GetFilename = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(PythonDLL))); - PyModule_Create2 = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(PythonDLL))); - PyImport_Import = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(PythonDLL))); - PyImport_ImportModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(PythonDLL))); - PyImport_ReloadModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(PythonDLL))); - PyImport_AddModule = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(PythonDLL))); - PyImport_GetModuleDict = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(PythonDLL))); - PySys_SetArgvEx = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(PythonDLL))); - PySys_GetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(PythonDLL))); - PySys_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(PythonDLL))); - PyType_Modified = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(PythonDLL))); - PyType_IsSubtype = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(PythonDLL))); - PyType_GenericNew = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(PythonDLL))); - PyType_GenericAlloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(PythonDLL))); - PyType_Ready = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(PythonDLL))); - _PyType_Lookup = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyType_LookupDelegate>(GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(PythonDLL))); - PyObject_GenericGetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(PythonDLL))); - PyObject_GenericSetAttr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(PythonDLL))); - _PyObject_GetDictPtr = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(PythonDLL))); - PyObject_GC_Del = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(PythonDLL))); - PyObject_GC_Track = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(PythonDLL))); - PyObject_GC_UnTrack = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(PythonDLL))); - PyMem_Malloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(PythonDLL))); - PyMem_Realloc = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(PythonDLL))); - PyMem_Free = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(PythonDLL))); - PyErr_SetString = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(PythonDLL))); - PyErr_SetObject = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(PythonDLL))); - PyErr_SetFromErrno = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(PythonDLL))); - PyErr_SetNone = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(PythonDLL))); - PyErr_ExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(PythonDLL))); - PyErr_GivenExceptionMatches = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(PythonDLL))); - PyErr_NormalizeException = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(PythonDLL))); - PyErr_Occurred = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(PythonDLL))); - PyErr_Fetch = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(PythonDLL))); - PyErr_Restore = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(PythonDLL))); - PyErr_Clear = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(PythonDLL))); - PyErr_Print = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(PythonDLL))); - PyMethod_Self = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(PythonDLL))); - PyMethod_Function = global::System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(PythonDLL))); + Py_IncRef = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IncRef), GetUnmanagedDll(PythonDLL))); + Py_DecRef = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_DecRef), GetUnmanagedDll(PythonDLL))); + Py_Initialize = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Initialize), GetUnmanagedDll(PythonDLL))); + Py_InitializeEx = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_InitializeEx), GetUnmanagedDll(PythonDLL))); + Py_IsInitialized = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_IsInitialized), GetUnmanagedDll(PythonDLL))); + Py_Finalize = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Finalize), GetUnmanagedDll(PythonDLL))); + Py_NewInterpreter = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_NewInterpreter), GetUnmanagedDll(PythonDLL))); + Py_EndInterpreter = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_EndInterpreter), GetUnmanagedDll(PythonDLL))); + PyThreadState_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_New), GetUnmanagedDll(PythonDLL))); + PyThreadState_Get = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Get), GetUnmanagedDll(PythonDLL))); + PyThread_get_key_value = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_key_value), GetUnmanagedDll(PythonDLL))); + PyThread_get_thread_ident = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_get_thread_ident), GetUnmanagedDll(PythonDLL))); + PyThread_set_key_value = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThread_set_key_value), GetUnmanagedDll(PythonDLL))); + PyThreadState_Swap = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyThreadState_Swap), GetUnmanagedDll(PythonDLL))); + PyGILState_Ensure = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(PythonDLL))); + PyGILState_Release = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(PythonDLL))); + PyGILState_GetThisThreadState = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(PythonDLL))); + Py_Main = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(PythonDLL))); + PyEval_InitThreads = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(PythonDLL))); + PyEval_ThreadsInitialized = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(PythonDLL))); + PyEval_AcquireLock = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireLock), GetUnmanagedDll(PythonDLL))); + PyEval_ReleaseLock = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseLock), GetUnmanagedDll(PythonDLL))); + PyEval_AcquireThread = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_AcquireThread), GetUnmanagedDll(PythonDLL))); + PyEval_ReleaseThread = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ReleaseThread), GetUnmanagedDll(PythonDLL))); + PyEval_SaveThread = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_SaveThread), GetUnmanagedDll(PythonDLL))); + PyEval_RestoreThread = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_RestoreThread), GetUnmanagedDll(PythonDLL))); + PyEval_GetBuiltins = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetBuiltins), GetUnmanagedDll(PythonDLL))); + PyEval_GetGlobals = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetGlobals), GetUnmanagedDll(PythonDLL))); + PyEval_GetLocals = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_GetLocals), GetUnmanagedDll(PythonDLL))); + Py_GetProgramName = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetProgramName), GetUnmanagedDll(PythonDLL))); + Py_SetProgramName = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetProgramName), GetUnmanagedDll(PythonDLL))); + Py_GetPythonHome = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPythonHome), GetUnmanagedDll(PythonDLL))); + Py_SetPythonHome = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPythonHome), GetUnmanagedDll(PythonDLL))); + Py_GetPath = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPath), GetUnmanagedDll(PythonDLL))); + Py_SetPath = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_SetPath), GetUnmanagedDll(PythonDLL))); + Py_GetVersion = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetVersion), GetUnmanagedDll(PythonDLL))); + Py_GetPlatform = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetPlatform), GetUnmanagedDll(PythonDLL))); + Py_GetCopyright = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCopyright), GetUnmanagedDll(PythonDLL))); + Py_GetCompiler = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetCompiler), GetUnmanagedDll(PythonDLL))); + Py_GetBuildInfo = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_GetBuildInfo), GetUnmanagedDll(PythonDLL))); + PyRun_SimpleString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_SimpleString), GetUnmanagedDll(PythonDLL))); + PyRun_String = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyRun_String), GetUnmanagedDll(PythonDLL))); + PyEval_EvalCode = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_EvalCode), GetUnmanagedDll(PythonDLL))); + Py_CompileString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_CompileString), GetUnmanagedDll(PythonDLL))); + PyImport_ExecCodeModule = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ExecCodeModule), GetUnmanagedDll(PythonDLL))); + PyCFunction_NewEx = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_NewEx), GetUnmanagedDll(PythonDLL))); + PyCFunction_Call = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCFunction_Call), GetUnmanagedDll(PythonDLL))); + PyObject_HasAttrString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_GetAttrString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_SetAttrString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttrString), GetUnmanagedDll(PythonDLL))); + PyObject_HasAttr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_HasAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GetAttr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_SetAttr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetItem), GetUnmanagedDll(PythonDLL))); + PyObject_SetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_SetItem), GetUnmanagedDll(PythonDLL))); + PyObject_DelItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_DelItem), GetUnmanagedDll(PythonDLL))); + PyObject_GetIter = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetIter), GetUnmanagedDll(PythonDLL))); + PyObject_Call = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Call), GetUnmanagedDll(PythonDLL))); + PyObject_CallObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_CallObject), GetUnmanagedDll(PythonDLL))); + PyObject_RichCompareBool = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_RichCompareBool), GetUnmanagedDll(PythonDLL))); + PyObject_IsInstance = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsInstance), GetUnmanagedDll(PythonDLL))); + PyObject_IsSubclass = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsSubclass), GetUnmanagedDll(PythonDLL))); + PyCallable_Check = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(PythonDLL))); + PyObject_IsTrue = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(PythonDLL))); + PyObject_Not = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(PythonDLL))); + _PyObject_Size = GetDelegateForFunctionPointer<_PyObject_SizeDelegate>(GetFunctionByName("PyObject_Size", GetUnmanagedDll(PythonDLL))); + PyObject_Hash = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(PythonDLL))); + PyObject_Repr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(PythonDLL))); + PyObject_Str = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(PythonDLL))); + PyObject_Unicode = GetDelegateForFunctionPointer(GetFunctionByName("PyObject_Str", GetUnmanagedDll(PythonDLL))); + PyObject_Dir = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_Dir), GetUnmanagedDll(PythonDLL))); + PyNumber_Int = GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_Long", GetUnmanagedDll(PythonDLL))); + PyNumber_Long = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Long), GetUnmanagedDll(PythonDLL))); + PyNumber_Float = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Float), GetUnmanagedDll(PythonDLL))); + PyNumber_Check = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Check), GetUnmanagedDll(PythonDLL))); + PyInt_FromLong = GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromLong", GetUnmanagedDll(PythonDLL))); + PyInt_AsLong = GetDelegateForFunctionPointer(GetFunctionByName("PyLong_AsLong", GetUnmanagedDll(PythonDLL))); + PyInt_FromString = GetDelegateForFunctionPointer(GetFunctionByName("PyLong_FromString", GetUnmanagedDll(PythonDLL))); + PyLong_FromLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromUnsignedLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromDouble = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromDouble), GetUnmanagedDll(PythonDLL))); + PyLong_FromLongLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromUnsignedLongLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromUnsignedLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_FromString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_FromString), GetUnmanagedDll(PythonDLL))); + PyLong_AsLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsUnsignedLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsLongLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsLongLong), GetUnmanagedDll(PythonDLL))); + PyLong_AsUnsignedLongLong = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyLong_AsUnsignedLongLong), GetUnmanagedDll(PythonDLL))); + PyFloat_FromDouble = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromDouble), GetUnmanagedDll(PythonDLL))); + PyFloat_FromString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_FromString), GetUnmanagedDll(PythonDLL))); + PyFloat_AsDouble = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyFloat_AsDouble), GetUnmanagedDll(PythonDLL))); + PyNumber_Add = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Add), GetUnmanagedDll(PythonDLL))); + PyNumber_Subtract = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Subtract), GetUnmanagedDll(PythonDLL))); + PyNumber_Multiply = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Multiply), GetUnmanagedDll(PythonDLL))); + PyNumber_Divide = GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_TrueDivide", GetUnmanagedDll(PythonDLL))); + PyNumber_And = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_And), GetUnmanagedDll(PythonDLL))); + PyNumber_Xor = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Xor), GetUnmanagedDll(PythonDLL))); + PyNumber_Or = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Or), GetUnmanagedDll(PythonDLL))); + PyNumber_Lshift = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Lshift), GetUnmanagedDll(PythonDLL))); + PyNumber_Rshift = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Rshift), GetUnmanagedDll(PythonDLL))); + PyNumber_Power = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Power), GetUnmanagedDll(PythonDLL))); + PyNumber_Remainder = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Remainder), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceAdd = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAdd), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceSubtract = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceSubtract), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceMultiply = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceMultiply), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceDivide = GetDelegateForFunctionPointer(GetFunctionByName("PyNumber_InPlaceTrueDivide", GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceAnd = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceAnd), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceXor = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceXor), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceOr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceOr), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceLshift = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceLshift), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceRshift = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRshift), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlacePower = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlacePower), GetUnmanagedDll(PythonDLL))); + PyNumber_InPlaceRemainder = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_InPlaceRemainder), GetUnmanagedDll(PythonDLL))); + PyNumber_Negative = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Negative), GetUnmanagedDll(PythonDLL))); + PyNumber_Positive = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Positive), GetUnmanagedDll(PythonDLL))); + PyNumber_Invert = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyNumber_Invert), GetUnmanagedDll(PythonDLL))); + PySequence_Check = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Check), GetUnmanagedDll(PythonDLL))); + PySequence_GetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetItem), GetUnmanagedDll(PythonDLL))); + PySequence_SetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetItem), GetUnmanagedDll(PythonDLL))); + PySequence_DelItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelItem), GetUnmanagedDll(PythonDLL))); + PySequence_GetSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_GetSlice), GetUnmanagedDll(PythonDLL))); + PySequence_SetSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_SetSlice), GetUnmanagedDll(PythonDLL))); + PySequence_DelSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_DelSlice), GetUnmanagedDll(PythonDLL))); + _PySequence_Size = GetDelegateForFunctionPointer<_PySequence_SizeDelegate>(GetFunctionByName("PySequence_Size", GetUnmanagedDll(PythonDLL))); + PySequence_Contains = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Contains), GetUnmanagedDll(PythonDLL))); + PySequence_Concat = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Concat), GetUnmanagedDll(PythonDLL))); + PySequence_Repeat = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Repeat), GetUnmanagedDll(PythonDLL))); + PySequence_Index = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Index), GetUnmanagedDll(PythonDLL))); + _PySequence_Count = GetDelegateForFunctionPointer<_PySequence_CountDelegate>(GetFunctionByName("PySequence_Count", GetUnmanagedDll(PythonDLL))); + PySequence_Tuple = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_Tuple), GetUnmanagedDll(PythonDLL))); + PySequence_List = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySequence_List), GetUnmanagedDll(PythonDLL))); + PyBytes_FromString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBytes_FromString), GetUnmanagedDll(PythonDLL))); + _PyBytes_Size = GetDelegateForFunctionPointer<_PyBytes_SizeDelegate>(GetFunctionByName("PyBytes_Size", GetUnmanagedDll(PythonDLL))); + _PyString_FromStringAndSize = GetDelegateForFunctionPointer<_PyString_FromStringAndSizeDelegate>(GetFunctionByName("PyUnicode_FromStringAndSize", GetUnmanagedDll(PythonDLL))); + PyUnicode_FromStringAndSize = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromStringAndSize), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromObject), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromEncodedObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromEncodedObject), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromKindAndData = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromKindAndData), GetUnmanagedDll(PythonDLL))); + _PyUnicode_GetSize = GetDelegateForFunctionPointer<_PyUnicode_GetSizeDelegate>(GetFunctionByName("PyUnicode_GetSize", GetUnmanagedDll(PythonDLL))); + PyUnicode_AsUnicode = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_AsUnicode), GetUnmanagedDll(PythonDLL))); + PyUnicode_FromOrdinal = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyUnicode_FromOrdinal), GetUnmanagedDll(PythonDLL))); + PyDict_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_New), GetUnmanagedDll(PythonDLL))); + PyDictProxy_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDictProxy_New), GetUnmanagedDll(PythonDLL))); + PyDict_GetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItem), GetUnmanagedDll(PythonDLL))); + PyDict_GetItemString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_GetItemString), GetUnmanagedDll(PythonDLL))); + PyDict_SetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItem), GetUnmanagedDll(PythonDLL))); + PyDict_SetItemString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_SetItemString), GetUnmanagedDll(PythonDLL))); + PyDict_DelItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItem), GetUnmanagedDll(PythonDLL))); + PyDict_DelItemString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_DelItemString), GetUnmanagedDll(PythonDLL))); + PyMapping_HasKey = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMapping_HasKey), GetUnmanagedDll(PythonDLL))); + PyDict_Keys = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Keys), GetUnmanagedDll(PythonDLL))); + PyDict_Values = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Values), GetUnmanagedDll(PythonDLL))); + PyDict_Items = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Items), GetUnmanagedDll(PythonDLL))); + PyDict_Copy = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Copy), GetUnmanagedDll(PythonDLL))); + PyDict_Update = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Update), GetUnmanagedDll(PythonDLL))); + PyDict_Clear = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyDict_Clear), GetUnmanagedDll(PythonDLL))); + _PyDict_Size = GetDelegateForFunctionPointer<_PyDict_SizeDelegate>(GetFunctionByName("PyDict_Size", GetUnmanagedDll(PythonDLL))); + PyList_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_New), GetUnmanagedDll(PythonDLL))); + PyList_AsTuple = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_AsTuple), GetUnmanagedDll(PythonDLL))); + PyList_GetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetItem), GetUnmanagedDll(PythonDLL))); + PyList_SetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetItem), GetUnmanagedDll(PythonDLL))); + PyList_Insert = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Insert), GetUnmanagedDll(PythonDLL))); + PyList_Append = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Append), GetUnmanagedDll(PythonDLL))); + PyList_Reverse = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Reverse), GetUnmanagedDll(PythonDLL))); + PyList_Sort = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_Sort), GetUnmanagedDll(PythonDLL))); + PyList_GetSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_GetSlice), GetUnmanagedDll(PythonDLL))); + PyList_SetSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyList_SetSlice), GetUnmanagedDll(PythonDLL))); + _PyList_Size = GetDelegateForFunctionPointer<_PyList_SizeDelegate>(GetFunctionByName("PyList_Size", GetUnmanagedDll(PythonDLL))); + PyTuple_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_New), GetUnmanagedDll(PythonDLL))); + PyTuple_GetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetItem), GetUnmanagedDll(PythonDLL))); + PyTuple_SetItem = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_SetItem), GetUnmanagedDll(PythonDLL))); + PyTuple_GetSlice = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyTuple_GetSlice), GetUnmanagedDll(PythonDLL))); + _PyTuple_Size = GetDelegateForFunctionPointer<_PyTuple_SizeDelegate>(GetFunctionByName("PyTuple_Size", GetUnmanagedDll(PythonDLL))); + PyIter_Next = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyIter_Next), GetUnmanagedDll(PythonDLL))); + PyModule_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_New), GetUnmanagedDll(PythonDLL))); + PyModule_GetName = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetName), GetUnmanagedDll(PythonDLL))); + PyModule_GetDict = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetDict), GetUnmanagedDll(PythonDLL))); + PyModule_GetFilename = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_GetFilename), GetUnmanagedDll(PythonDLL))); + PyModule_Create2 = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyModule_Create2), GetUnmanagedDll(PythonDLL))); + PyImport_Import = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_Import), GetUnmanagedDll(PythonDLL))); + PyImport_ImportModule = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ImportModule), GetUnmanagedDll(PythonDLL))); + PyImport_ReloadModule = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_ReloadModule), GetUnmanagedDll(PythonDLL))); + PyImport_AddModule = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_AddModule), GetUnmanagedDll(PythonDLL))); + PyImport_GetModuleDict = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyImport_GetModuleDict), GetUnmanagedDll(PythonDLL))); + PySys_SetArgvEx = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetArgvEx), GetUnmanagedDll(PythonDLL))); + PySys_GetObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_GetObject), GetUnmanagedDll(PythonDLL))); + PySys_SetObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PySys_SetObject), GetUnmanagedDll(PythonDLL))); + PyType_Modified = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Modified), GetUnmanagedDll(PythonDLL))); + PyType_IsSubtype = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_IsSubtype), GetUnmanagedDll(PythonDLL))); + PyType_GenericNew = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericNew), GetUnmanagedDll(PythonDLL))); + PyType_GenericAlloc = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_GenericAlloc), GetUnmanagedDll(PythonDLL))); + PyType_Ready = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(PythonDLL))); + _PyType_Lookup = GetDelegateForFunctionPointer<_PyType_LookupDelegate>(GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(PythonDLL))); + PyObject_GenericGetAttr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(PythonDLL))); + PyObject_GenericSetAttr = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(PythonDLL))); + _PyObject_GetDictPtr = GetDelegateForFunctionPointer<_PyObject_GetDictPtrDelegate>(GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(PythonDLL))); + PyObject_GC_Del = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(PythonDLL))); + PyObject_GC_Track = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(PythonDLL))); + PyObject_GC_UnTrack = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(PythonDLL))); + PyMem_Malloc = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Malloc), GetUnmanagedDll(PythonDLL))); + PyMem_Realloc = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Realloc), GetUnmanagedDll(PythonDLL))); + PyMem_Free = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMem_Free), GetUnmanagedDll(PythonDLL))); + PyErr_SetString = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetString), GetUnmanagedDll(PythonDLL))); + PyErr_SetObject = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetObject), GetUnmanagedDll(PythonDLL))); + PyErr_SetFromErrno = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetFromErrno), GetUnmanagedDll(PythonDLL))); + PyErr_SetNone = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_SetNone), GetUnmanagedDll(PythonDLL))); + PyErr_ExceptionMatches = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_ExceptionMatches), GetUnmanagedDll(PythonDLL))); + PyErr_GivenExceptionMatches = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_GivenExceptionMatches), GetUnmanagedDll(PythonDLL))); + PyErr_NormalizeException = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_NormalizeException), GetUnmanagedDll(PythonDLL))); + PyErr_Occurred = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Occurred), GetUnmanagedDll(PythonDLL))); + PyErr_Fetch = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Fetch), GetUnmanagedDll(PythonDLL))); + PyErr_Restore = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Restore), GetUnmanagedDll(PythonDLL))); + PyErr_Clear = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Clear), GetUnmanagedDll(PythonDLL))); + PyErr_Print = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(PythonDLL))); + PyMethod_Self = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(PythonDLL))); + PyMethod_Function = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(PythonDLL))); + } + + static T GetDelegateForFunctionPointer(IntPtr functionPointer) { +#if NETFX + return (T)(object)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(T)); +#else + return Marshal.GetDelegateForFunctionPointer(functionPointer); +#endif } static global::System.IntPtr GetUnmanagedDll(string libraryName) { @@ -3303,4 +3311,12 @@ enum Py2 { } } } + +#if NETFX + class RuntimeInformation{ + public static bool IsOSPlatform(OSPlatform platform){return platform == OSPlatform.Windows;} + } + + enum OSPlatform{ Windows, Linux, OSX } +#endif } From 1260c760cdffb44794a52934503bf9304d6ec320 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 14 Apr 2019 14:46:39 -0700 Subject: [PATCH 032/240] moved default arg converter to its own file; cached converter lookup --- src/runtime/defaultpyargconverter.cs | 111 ++++++++++++++++++++++++++ src/runtime/methodbinder.cs | 112 +++++---------------------- src/runtime/pyargconverter.cs | 30 ------- 3 files changed, 130 insertions(+), 123 deletions(-) create mode 100644 src/runtime/defaultpyargconverter.cs diff --git a/src/runtime/defaultpyargconverter.cs b/src/runtime/defaultpyargconverter.cs new file mode 100644 index 000000000..b2dd5d236 --- /dev/null +++ b/src/runtime/defaultpyargconverter.cs @@ -0,0 +1,111 @@ +namespace Python.Runtime { + using System; + + /// + /// The implementation of used by default + /// + public class DefaultPyArgumentConverter: IPyArgumentConverter + { + /// + /// Gets the singleton instance. + /// + public static DefaultPyArgumentConverter Instance { get; } = new DefaultPyArgumentConverter(); + + /// + /// + /// Attempts to convert an argument passed by Python to the specified parameter type. + /// + /// Unmanaged pointer to the Python argument value + /// The expected type of the parameter + /// true if the method is overloaded + /// This parameter will receive the converted value, matching the specified type + /// This parameter will be set to true, + /// if the final type needs to be marshaled as an out argument. + /// true, if the object matches requested type, + /// and conversion was successful, otherwise false + public virtual bool TryConvertArgument( + IntPtr pyarg, Type parameterType, bool needsResolution, + out object arg, out bool isOut) + { + arg = null; + isOut = false; + Type clrType = TryComputeClrArgumentType(parameterType, pyarg, needsResolution: needsResolution); + if (clrType == null) + { + return false; + } + + if (!Converter.ToManaged(pyarg, clrType, out arg, false)) + { + Exceptions.Clear(); + return false; + } + + isOut = clrType.IsByRef; + return true; + } + + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) + { + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + Type clrType = null; + IntPtr pyArgType; + if (needsResolution) + { + // HACK: each overload should be weighted in some way instead + pyArgType = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyArgType != IntPtr.Zero) + { + clrType = Converter.GetTypeByAlias(pyArgType); + } + Runtime.XDecref(pyArgType); + } + + if (clrType != null) + { + if ((parameterType != typeof(object)) && (parameterType != clrType)) + { + IntPtr pyParamType = Converter.GetPythonTypeByAlias(parameterType); + pyArgType = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + + bool typeMatch = false; + if (pyArgType != IntPtr.Zero && pyParamType == pyArgType) + { + typeMatch = true; + clrType = parameterType; + } + if (!typeMatch) + { + // this takes care of enum values + TypeCode argTypeCode = Type.GetTypeCode(parameterType); + TypeCode paramTypeCode = Type.GetTypeCode(clrType); + if (argTypeCode == paramTypeCode) + { + typeMatch = true; + clrType = parameterType; + } + } + Runtime.XDecref(pyArgType); + if (!typeMatch) + { + return null; + } + } + else + { + clrType = parameterType; + } + } + else + { + clrType = parameterType; + } + + return clrType; + } + } +} diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index c970c7e82..4b654f8a9 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Reflection; @@ -177,8 +178,7 @@ IPyArgumentConverter GetArgumentConverter() { Type converterType = null; foreach (MethodBase method in this.methods) { - var attribute = method.DeclaringType?.GetCustomAttribute() - ?? method.DeclaringType?.Assembly.GetCustomAttribute(); + PyArgConverterAttribute attribute = TryGetArgConverter(method.DeclaringType); if (converterType == null) { if (attribute == null) continue; @@ -194,6 +194,23 @@ IPyArgumentConverter GetArgumentConverter() { return converter ?? DefaultPyArgumentConverter.Instance; } + static readonly ConcurrentDictionary ArgConverterCache = + new ConcurrentDictionary(); + static PyArgConverterAttribute TryGetArgConverter(Type type) { + if (type == null) return null; + + return ArgConverterCache.GetOrAdd(type, declaringType => + declaringType + .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: false) + .OfType() + .SingleOrDefault() + ?? declaringType.Assembly + .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: false) + .OfType() + .SingleOrDefault() + ); + } + /// /// Precedence algorithm largely lifted from Jython - the concerns are /// generally the same so we'll start with this and tweak as necessary. @@ -443,97 +460,6 @@ object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, return margs; } - internal static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, - out object arg, out bool isOut) - { - arg = null; - isOut = false; - var clrtype = TryComputeClrArgumentType(parameterType, op, needsResolution: needsResolution); - if (clrtype == null) - { - return false; - } - - if (!Converter.ToManaged(op, clrtype, out arg, false)) - { - Exceptions.Clear(); - return false; - } - - isOut = clrtype.IsByRef; - return true; - } - - static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) - { - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - Type clrtype = null; - IntPtr pyoptype; - if (needsResolution) - { - // HACK: each overload should be weighted in some way instead - pyoptype = Runtime.PyObject_Type(argument); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - clrtype = Converter.GetTypeByAlias(pyoptype); - } - Runtime.XDecref(pyoptype); - } - - if (clrtype != null) - { - var typematch = false; - if ((parameterType != typeof(object)) && (parameterType != clrtype)) - { - IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType); - pyoptype = Runtime.PyObject_Type(argument); - Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) - { - if (pytype != pyoptype) - { - typematch = false; - } - else - { - typematch = true; - clrtype = parameterType; - } - } - if (!typematch) - { - // this takes care of enum values - TypeCode argtypecode = Type.GetTypeCode(parameterType); - TypeCode paramtypecode = Type.GetTypeCode(clrtype); - if (argtypecode == paramtypecode) - { - typematch = true; - clrtype = parameterType; - } - } - Runtime.XDecref(pyoptype); - if (!typematch) - { - return null; - } - } - else - { - typematch = true; - clrtype = parameterType; - } - } - else - { - clrtype = parameterType; - } - - return clrtype; - } - static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, out bool paramsArray, out ArrayList defaultArgList) diff --git a/src/runtime/pyargconverter.cs b/src/runtime/pyargconverter.cs index 69dfc714f..cf6be7b6d 100644 --- a/src/runtime/pyargconverter.cs +++ b/src/runtime/pyargconverter.cs @@ -21,36 +21,6 @@ bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, out object arg, out bool isOut); } - /// - /// The implementation of used by default - /// - public class DefaultPyArgumentConverter: IPyArgumentConverter { - /// - /// Gets the singleton instance. - /// - public static DefaultPyArgumentConverter Instance { get; } = new DefaultPyArgumentConverter(); - - /// - /// Attempts to convert an argument passed by Python to the specified parameter type. - /// - /// Unmanaged pointer to the Python argument value - /// The expected type of the parameter - /// true if the method is overloaded - /// This parameter will receive the converted value, matching the specified type - /// This parameter will be set to true, - /// if the final type needs to be marshaled as an out argument. - /// true, if the object matches requested type, - /// and conversion was successful, otherwise false - public virtual bool TryConvertArgument( - IntPtr pyarg, Type parameterType, bool needsResolution, - out object arg, out bool isOut) - { - return MethodBinder.TryConvertArgument( - pyarg, parameterType, needsResolution, - out arg, out isOut); - } - } - /// /// Specifies an argument converter to be used, when methods in this class/assembly are called from Python. /// From 705358e7c97338b3d6f5f26d06ae10a601241ef0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 13 May 2019 22:42:24 -0700 Subject: [PATCH 033/240] dropped Python 2 support; generate a single universal binary --- pythonnet.15.sln | 374 ++---------------- src/clrmodule/ClrModule.cs | 13 - src/clrmodule/clrmodule.15.csproj | 1 - src/console/Console.15.csproj | 1 - .../Python.EmbeddingTest.15.csproj | 3 +- src/runtime/CustomMarshaler.cs | 8 +- src/runtime/Python.Runtime.15.csproj | 58 +-- src/runtime/Python.Runtime.Ref.csproj | 41 -- src/runtime/converter.cs | 99 +---- src/runtime/delegateobject.cs | 9 - src/runtime/exceptions.cs | 7 +- src/runtime/importhook.cs | 17 +- src/runtime/interop.cs | 38 +- src/runtime/interop34.cs | 22 +- src/runtime/interop35.cs | 22 +- src/runtime/interop36.cs | 22 +- src/runtime/interop37.cs | 22 +- src/runtime/pythonengine.cs | 12 - src/runtime/runtime.cs | 335 ++++------------ src/runtime/typemanager.cs | 11 - src/runtime/{interop27.cs => typeoffset.cs} | 46 +-- src/testing/Python.Test.15.csproj | 1 - tools/geninterop/geninterop.py | 35 +- 23 files changed, 155 insertions(+), 1042 deletions(-) delete mode 100644 src/runtime/Python.Runtime.Ref.csproj rename src/runtime/{interop27.cs => typeoffset.cs} (81%) diff --git a/pythonnet.15.sln b/pythonnet.15.sln index 260b61d43..18787df5b 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.352 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.15", "src\runtime\Python.Runtime.15.csproj", "{2759F4FF-716B-4828-916F-50FA86613DFC}" EndProject @@ -18,362 +18,32 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{B6E8FE48-C global.json = global.json EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.Ref", "src\runtime\Python.Runtime.Ref.csproj", "{9AE47FC5-A656-4071-85BE-ABE97EB6F38B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - DebugMono|Any CPU = DebugMono|Any CPU - DebugMono|x64 = DebugMono|x64 - DebugMono|x86 = DebugMono|x86 - DebugMonoPY3|Any CPU = DebugMonoPY3|Any CPU - DebugMonoPY3|x64 = DebugMonoPY3|x64 - DebugMonoPY3|x86 = DebugMonoPY3|x86 - DebugWin|Any CPU = DebugWin|Any CPU - DebugWin|x64 = DebugWin|x64 - DebugWin|x86 = DebugWin|x86 - DebugWinPY3|Any CPU = DebugWinPY3|Any CPU - DebugWinPY3|x64 = DebugWinPY3|x64 - DebugWinPY3|x86 = DebugWinPY3|x86 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - ReleaseMono|Any CPU = ReleaseMono|Any CPU - ReleaseMono|x64 = ReleaseMono|x64 - ReleaseMono|x86 = ReleaseMono|x86 - ReleaseMonoPY3|Any CPU = ReleaseMonoPY3|Any CPU - ReleaseMonoPY3|x64 = ReleaseMonoPY3|x64 - ReleaseMonoPY3|x86 = ReleaseMonoPY3|x86 - ReleaseWin|Any CPU = ReleaseWin|Any CPU - ReleaseWin|x64 = ReleaseWin|x64 - ReleaseWin|x86 = ReleaseWin|x86 - ReleaseWinPY3|Any CPU = ReleaseWinPY3|Any CPU - ReleaseWinPY3|x64 = ReleaseWinPY3|x64 - ReleaseWinPY3|x86 = ReleaseWinPY3|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.ActiveCfg = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.Build.0 = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.ActiveCfg = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x64.Build.0 = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.ActiveCfg = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|x86.Build.0 = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|Any CPU.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x64.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.ActiveCfg = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMono|x86.Build.0 = DebugMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|Any CPU.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|Any CPU.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x64.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWin|x86.Build.0 = DebugWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|Any CPU.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.ActiveCfg = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x64.Build.0 = Debug3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.DebugWinPY3|x86.Build.0 = DebugWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.ActiveCfg = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.Build.0 = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.ActiveCfg = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x64.Build.0 = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.ActiveCfg = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|x86.Build.0 = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|Any CPU.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x64.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.ActiveCfg = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMono|x86.Build.0 = ReleaseMono|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|Any CPU.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|Any CPU.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|Any CPU.Build.0 = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.ActiveCfg = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x64.Build.0 = Release3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|Any CPU - {2759F4FF-716B-4828-916F-50FA86613DFC}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|Any CPU - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x64.Build.0 = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|x86.Build.0 = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x64.Build.0 = DebugMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMono|x86.Build.0 = DebugMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x64.Build.0 = DebugWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWin|x86.Build.0 = DebugWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x64.Build.0 = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|x86.Build.0 = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x64.Build.0 = DebugWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWin|x86.Build.0 = DebugWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x64.Build.0 = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|x86.Build.0 = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x64.Build.0 = DebugMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMono|x86.Build.0 = DebugMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x64.Build.0 = DebugWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWin|x86.Build.0 = DebugWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {CDAD305F-8E72-492C-A314-64CF58D472A0}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.ActiveCfg = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x64.Build.0 = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|x86.Build.0 = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|Any CPU.ActiveCfg = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x64.Build.0 = DebugMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMono|x86.Build.0 = DebugMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|Any CPU.ActiveCfg = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x64.Build.0 = DebugWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWin|x86.Build.0 = DebugWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|Any CPU.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.ActiveCfg = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x64.Build.0 = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|x86.Build.0 = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|Any CPU.ActiveCfg = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|Any CPU.ActiveCfg = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|Any CPU.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {F94B547A-E97E-4500-8D53-B4D64D076E5F}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|Any CPU.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|Any CPU.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x64.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x64.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x86.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Debug|x86.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|Any CPU.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|Any CPU.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x64.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x64.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x86.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMono|x86.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|Any CPU.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|Any CPU.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x64.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x64.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x86.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugMonoPY3|x86.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|Any CPU.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|Any CPU.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x64.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x64.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x86.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWin|x86.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|Any CPU.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|Any CPU.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x64.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x64.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x86.ActiveCfg = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.DebugWinPY3|x86.Build.0 = Debug3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|Any CPU.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|Any CPU.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x64.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x64.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x86.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.Release|x86.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|Any CPU.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|Any CPU.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x64.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x64.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x86.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMono|x86.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|Any CPU.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|Any CPU.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x64.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x64.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x86.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseMonoPY3|x86.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|Any CPU.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|Any CPU.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x64.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x64.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x86.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWin|x86.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|Any CPU.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|Any CPU.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x64.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x64.Build.0 = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x86.ActiveCfg = Release3|Any CPU - {9AE47FC5-A656-4071-85BE-ABE97EB6F38B}.ReleaseWinPY3|x86.Build.0 = Release3|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.Build.0 = Release|Any CPU + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.ActiveCfg = Debug|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.Build.0 = Debug|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = Release|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = Release|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.ActiveCfg = Debug|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.Build.0 = Debug|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.ActiveCfg = Release|x86 + {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.Build.0 = Release|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.ActiveCfg = Debug|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Debug|Any CPU.Build.0 = Debug|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.ActiveCfg = Release|x86 + {CDAD305F-8E72-492C-A314-64CF58D472A0}.Release|Any CPU.Build.0 = Release|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Debug|Any CPU.Build.0 = Debug|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.ActiveCfg = Release|x86 + {F94B547A-E97E-4500-8D53-B4D64D076E5F}.Release|Any CPU.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/clrmodule/ClrModule.cs b/src/clrmodule/ClrModule.cs index 3bb3a533b..de1b6ee77 100644 --- a/src/clrmodule/ClrModule.cs +++ b/src/clrmodule/ClrModule.cs @@ -30,13 +30,8 @@ public class clrModule { -#if PYTHON3 [DllExport("PyInit_clr", CallingConvention.StdCall)] public static IntPtr PyInit_clr() -#elif PYTHON2 - [DllExport("initclr", CallingConvention.StdCall)] - public static void initclr() -#endif { DebugPrint("Attempting to load 'Python.Runtime' using standard binding rules."); #if USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN @@ -95,11 +90,7 @@ public static void initclr() catch (InvalidOperationException) { DebugPrint("Could not load 'Python.Runtime'."); -#if PYTHON3 return IntPtr.Zero; -#elif PYTHON2 - return; -#endif } } @@ -107,11 +98,7 @@ public static void initclr() // So now we get the PythonEngine and execute the InitExt method on it. Type pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); -#if PYTHON3 return (IntPtr)pythonEngineType.InvokeMember("InitExt", BindingFlags.InvokeMethod, null, null, null); -#elif PYTHON2 - pythonEngineType.InvokeMember("InitExt", BindingFlags.InvokeMethod, null, null, null); -#endif } /// diff --git a/src/clrmodule/clrmodule.15.csproj b/src/clrmodule/clrmodule.15.csproj index 2585ffdd2..da2f0a0c4 100644 --- a/src/clrmodule/clrmodule.15.csproj +++ b/src/clrmodule/clrmodule.15.csproj @@ -5,7 +5,6 @@ net40 x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 clrmodule clrmodule clrmodule diff --git a/src/console/Console.15.csproj b/src/console/Console.15.csproj index dc8fc72c1..2fbd84535 100644 --- a/src/console/Console.15.csproj +++ b/src/console/Console.15.csproj @@ -3,7 +3,6 @@ netcoreapp2.0 x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Exe nPython Python.Runtime diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index b8aa57a61..c7d247df7 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -4,7 +4,6 @@ netcoreapp2.0 x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Exe false Python.EmbeddingTest @@ -86,7 +85,7 @@ - + diff --git a/src/runtime/CustomMarshaler.cs b/src/runtime/CustomMarshaler.cs index 90bb77a71..8f50e2c3f 100644 --- a/src/runtime/CustomMarshaler.cs +++ b/src/runtime/CustomMarshaler.cs @@ -120,9 +120,7 @@ public static int GetUnicodeByteLength(IntPtr p) /// public static IntPtr Py3UnicodePy2StringtoPtr(string s) { - return Runtime.IsPython3 - ? Instance.MarshalManagedToNative(s) - : Marshal.StringToHGlobalAnsi(s); + return Instance.MarshalManagedToNative(s); } /// @@ -137,9 +135,7 @@ public static IntPtr Py3UnicodePy2StringtoPtr(string s) /// public static string PtrToPy3UnicodePy2String(IntPtr p) { - return Runtime.IsPython3 - ? PtrToStringUni(p) - : Marshal.PtrToStringAnsi(p); + return PtrToStringUni(p); } } diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 2f9fb2cdd..a0186916c 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,14 +1,11 @@ - + netstandard2.0;net40 - true - unix;win AnyCPU - Debug3;Release3;DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Python.Runtime Python.Runtime Python.Runtime.UnofficialNetStandard - 2.4.0 + 3.0.0 true false false @@ -31,63 +28,24 @@ $(DefineConstants);NETFX $(DefineConstants);NETSTANDARD $(DefineConstants);TRACE;DEBUG - $(PYTHONNET_PY2_VERSION) - PYTHON27 - $(PYTHONNET_PY3_VERSION) - PYTHON36 $(PYTHONNET_MULTIRUNTIME_DEFINE_CONSTANTS) - - MONO_LINUX;PYTHON_WITH_PYMALLOC - - $(PYTHONNET_WIN_DEFINE_CONSTANTS) - - $(PYTHONNET_MONO_DEFINE_CONSTANTS) - MONO_LINUX;PYTHON_WITH_PYMALLOC - + false full - + true portable - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonMonoDefineConstants) - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMonoDefineConstants) - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonMonoDefineConstants);TRACE;DEBUG - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMonoDefineConstants);TRACE;DEBUG - - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonWinDefineConstants) - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonWinDefineConstants) + + $(DefineConstants);$(PythonMultiRuntimeDefineConstants);TRACE;DEBUG - - $(DefineConstants);PYTHON2;$(Python2Version);$(PythonWinDefineConstants);TRACE;DEBUG + + $(DefineConstants);$(PythonMultiRuntimeDefineConstants) - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonWinDefineConstants);TRACE;DEBUG - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMultiRuntimeDefineConstants);TRACE;DEBUG - - - $(DefineConstants);PYTHON3;$(Python3Version);$(PythonMultiRuntimeDefineConstants) - - - - - diff --git a/src/runtime/Python.Runtime.Ref.csproj b/src/runtime/Python.Runtime.Ref.csproj deleted file mode 100644 index 448138721..000000000 --- a/src/runtime/Python.Runtime.Ref.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - netstandard2.0 - Debug3;Release3 - false - true - Python.Runtime - Python.Runtime - True - bin\ref\ - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - - false - false - false - false - false - false - - $(PYTHONNET_PY2_VERSION) - PYTHON27 - $(PYTHONNET_PY3_VERSION) - PYTHON36 - - $(DefineConstants);XPLAT;NETSTANDARD;$(Python3Version);PYTHON3 - - - - - - - - - - - clr.py - - - - diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 1883dc32b..6d91ccfcd 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -86,9 +86,6 @@ internal static IntPtr GetPythonTypeByAlias(Type op) if (op == int32Type) return Runtime.PyIntType; - if (op == int64Type && Runtime.IsPython2) - return Runtime.PyLongType; - if (op == int64Type) return Runtime.PyIntType; @@ -461,62 +458,34 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo case TypeCode.Int32: // Trickery to support 64-bit platforms. - if (Runtime.IsPython2 && Runtime.Is32Bit) + op = Runtime.PyNumber_Long(value); + if (op == IntPtr.Zero) { - op = Runtime.PyNumber_Int(value); - - // As of Python 2.3, large ints magically convert :( - if (Runtime.PyLong_Check(op)) + Exceptions.Clear(); + if (Exceptions.ExceptionMatches(overflow)) { - Runtime.XDecref(op); goto overflow; } - - if (op == IntPtr.Zero) - { - if (Exceptions.ExceptionMatches(overflow)) - { - goto overflow; - } - goto type_error; - } - ival = (int)Runtime.PyInt_AsLong(op); - Runtime.XDecref(op); - result = ival; - return true; + goto type_error; } - else // Python3 always use PyLong API + long ll = (long)Runtime.PyLong_AsLongLong(op); + Runtime.XDecref(op); + if (ll == -1 && Exceptions.ErrorOccurred()) { - op = Runtime.PyNumber_Long(value); - if (op == IntPtr.Zero) - { - Exceptions.Clear(); - if (Exceptions.ExceptionMatches(overflow)) - { - goto overflow; - } - goto type_error; - } - long ll = (long)Runtime.PyLong_AsLongLong(op); - Runtime.XDecref(op); - if (ll == -1 && Exceptions.ErrorOccurred()) - { - goto overflow; - } - if (ll > Int32.MaxValue || ll < Int32.MinValue) - { - goto overflow; - } - result = (int)ll; - return true; + goto overflow; } + if (ll > Int32.MaxValue || ll < Int32.MinValue) + { + goto overflow; + } + result = (int)ll; + return true; case TypeCode.Boolean: result = Runtime.PyObject_IsTrue(value) != 0; return true; case TypeCode.Byte: -#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) @@ -527,18 +496,6 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo } goto type_error; } -#elif PYTHON2 - if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) - { - if (Runtime.PyString_Size(value) == 1) - { - op = Runtime.PyString_AsString(value); - result = (byte)Marshal.ReadByte(op); - return true; - } - goto type_error; - } -#endif op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) @@ -561,7 +518,6 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo return true; case TypeCode.SByte: -#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) @@ -572,18 +528,6 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo } goto type_error; } -#elif PYTHON2 - if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) - { - if (Runtime.PyString_Size(value) == 1) - { - op = Runtime.PyString_AsString(value); - result = (sbyte)Marshal.ReadByte(op); - return true; - } - goto type_error; - } -#endif op = Runtime.PyNumber_Int(value); if (op == IntPtr.Zero) @@ -606,7 +550,6 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo return true; case TypeCode.Char: -#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) @@ -617,18 +560,6 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo } goto type_error; } -#elif PYTHON2 - if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) - { - if (Runtime.PyString_Size(value) == 1) - { - op = Runtime.PyString_AsString(value); - result = (char)Marshal.ReadByte(op); - return true; - } - goto type_error; - } -#endif else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType)) { if (Runtime.PyUnicode_GetSize(value) == 1) diff --git a/src/runtime/delegateobject.cs b/src/runtime/delegateobject.cs index e1103cbc7..c9aad9898 100644 --- a/src/runtime/delegateobject.cs +++ b/src/runtime/delegateobject.cs @@ -96,7 +96,6 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) /// /// Implements __cmp__ for reflected delegate types. /// -#if PYTHON3 // TODO: Doesn't PY2 implement tp_richcompare too? public new static IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { if (op != Runtime.Py_EQ && op != Runtime.Py_NE) @@ -126,13 +125,5 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) Runtime.XIncref(pyfalse); return pyfalse; } -#elif PYTHON2 - public static int tp_compare(IntPtr ob, IntPtr other) - { - Delegate d1 = GetTrueDelegate(ob); - Delegate d2 = GetTrueDelegate(other); - return d1 == d2 ? 0 : -1; - } -#endif } } diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 8bed0abfd..13c841bca 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -80,7 +80,7 @@ private Exceptions() /// internal static void Initialize() { - string exceptionsModuleName = Runtime.IsPython3 ? "builtins" : "exceptions"; + string exceptionsModuleName = "builtins"; exceptions_module = Runtime.PyImport_ImportModule(exceptionsModuleName); Exceptions.ErrorCheck(exceptions_module); @@ -157,13 +157,11 @@ internal static void SetArgsAndCause(IntPtr ob) Marshal.WriteIntPtr(ob, ExceptionOffset.args, args); -#if PYTHON3 if (e.InnerException != null) { IntPtr cause = CLRObject.GetInstHandle(e.InnerException); Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause); } -#endif } /// @@ -363,9 +361,6 @@ puplic static variables on the Exceptions class filled in from public static IntPtr Exception; public static IntPtr StopIteration; public static IntPtr GeneratorExit; -#if PYTHON2 - public static IntPtr StandardError; -#endif public static IntPtr ArithmeticError; public static IntPtr LookupError; diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index 7e4a208f5..b5c520485 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -13,7 +13,6 @@ internal class ImportHook private static MethodWrapper hook; private static IntPtr py_clr_module; -#if PYTHON3 private static IntPtr module_def = IntPtr.Zero; internal static void InitializeModuleDef() @@ -23,7 +22,6 @@ internal static void InitializeModuleDef() module_def = ModuleDefOffset.AllocModuleDef("clr"); } } -#endif /// /// Initialization performed on startup of the Python runtime. @@ -36,9 +34,7 @@ internal static void Initialize() // modules (Python doesn't provide a way to emulate packages). IntPtr dict = Runtime.PyImport_GetModuleDict(); - IntPtr mod = Runtime.IsPython3 - ? Runtime.PyImport_ImportModule("builtins") - : Runtime.PyDict_GetItemString(dict, "__builtin__"); + IntPtr mod = Runtime.PyImport_ImportModule("builtins"); py_import = Runtime.PyObject_GetAttrString(mod, "__import__"); hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc"); @@ -47,7 +43,6 @@ internal static void Initialize() root = new CLRModule(); -#if PYTHON3 // create a python module with the same methods as the clr module-like object InitializeModuleDef(); py_clr_module = Runtime.PyModule_Create2(module_def, 3); @@ -58,10 +53,6 @@ internal static void Initialize() clr_dict = (IntPtr)Marshal.PtrToStructure(clr_dict, typeof(IntPtr)); Runtime.PyDict_Update(mod_dict, clr_dict); -#elif PYTHON2 - Runtime.XIncref(root.pyHandle); // we are using the module two times - py_clr_module = root.pyHandle; // Alias handle for PY2/PY3 -#endif Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module); Runtime.PyDict_SetItemString(dict, "clr", py_clr_module); } @@ -87,12 +78,6 @@ public static IntPtr GetCLRModule(IntPtr? fromList = null) { root.InitializePreload(); - if (Runtime.IsPython2) - { - Runtime.XIncref(py_clr_module); - return py_clr_module; - } - // Python 3 // update the module dictionary with the contents of the root dictionary root.LoadNames(); diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 6ce6f5e06..bb5b1de7e 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -153,14 +153,10 @@ public static int Size() // (start after PyObject_HEAD) public static int dict = 0; public static int args = 0; -#if PYTHON2 - public static int message = 0; -#elif PYTHON3 public static int traceback = 0; public static int context = 0; public static int cause = 0; public static int suppress_context = 0; -#endif // extra c# data public static int ob_dict; @@ -168,7 +164,6 @@ public static int Size() } -#if PYTHON3 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal class BytesOffset { @@ -259,7 +254,6 @@ public static void FreeModuleDef(IntPtr ptr) public static int name = 0; } -#endif // PYTHON3 /// /// TypeFlags(): The actual bit values for the Type Flags stored @@ -269,17 +263,6 @@ public static void FreeModuleDef(IntPtr ptr) /// internal class TypeFlags { -#if PYTHON2 // these flags were removed in Python 3 - public static int HaveGetCharBuffer = (1 << 0); - public static int HaveSequenceIn = (1 << 1); - public static int GC = 0; - public static int HaveInPlaceOps = (1 << 3); - public static int CheckTypes = (1 << 4); - public static int HaveRichCompare = (1 << 5); - public static int HaveWeakRefs = (1 << 6); - public static int HaveIter = (1 << 7); - public static int HaveClass = (1 << 8); -#endif public static int HeapType = (1 << 9); public static int BaseType = (1 << 10); public static int Ready = (1 << 12); @@ -307,23 +290,10 @@ internal class TypeFlags public static int BaseExceptionSubclass = (1 << 30); public static int TypeSubclass = (1 << 31); -#if PYTHON2 // Default flags for Python 2 - public static int Default = ( - HaveGetCharBuffer | - HaveSequenceIn | - HaveInPlaceOps | - HaveRichCompare | - HaveWeakRefs | - HaveIter | - HaveClass | - HaveStacklessExtension | - HaveIndex | - 0); -#elif PYTHON3 // Default flags for Python 3 + public static int Default = ( HaveStacklessExtension | HaveVersionTag); -#endif } @@ -382,9 +352,6 @@ static Interop() pmap["nb_add"] = p["BinaryFunc"]; pmap["nb_subtract"] = p["BinaryFunc"]; pmap["nb_multiply"] = p["BinaryFunc"]; -#if PYTHON2 - pmap["nb_divide"] = p["BinaryFunc"]; -#endif pmap["nb_remainder"] = p["BinaryFunc"]; pmap["nb_divmod"] = p["BinaryFunc"]; pmap["nb_power"] = p["TernaryFunc"]; @@ -407,9 +374,6 @@ static Interop() pmap["nb_inplace_add"] = p["BinaryFunc"]; pmap["nb_inplace_subtract"] = p["BinaryFunc"]; pmap["nb_inplace_multiply"] = p["BinaryFunc"]; -#if PYTHON2 - pmap["nb_inplace_divide"] = p["BinaryFunc"]; -#endif pmap["nb_inplace_remainder"] = p["BinaryFunc"]; pmap["nb_inplace_power"] = p["TernaryFunc"]; pmap["nb_inplace_lshift"] = p["BinaryFunc"]; diff --git a/src/runtime/interop34.cs b/src/runtime/interop34.cs index 6857ff2d0..2723aacdc 100644 --- a/src/runtime/interop34.cs +++ b/src/runtime/interop34.cs @@ -1,8 +1,6 @@ // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. - -#if PYTHON34 using System; using System.Collections; using System.Collections.Specialized; @@ -13,24 +11,8 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + internal class TypeOffset34 { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; @@ -140,5 +122,3 @@ public static int magic() public static int members = 0; } } - -#endif diff --git a/src/runtime/interop35.cs b/src/runtime/interop35.cs index a30bfa4fd..a95fbed9a 100644 --- a/src/runtime/interop35.cs +++ b/src/runtime/interop35.cs @@ -1,8 +1,6 @@ // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. - -#if PYTHON35 using System; using System.Collections; using System.Collections.Specialized; @@ -13,24 +11,8 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + internal class TypeOffset35 { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; @@ -145,5 +127,3 @@ public static int magic() public static int members = 0; } } - -#endif diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs index c46bcc2f5..058be9639 100644 --- a/src/runtime/interop36.cs +++ b/src/runtime/interop36.cs @@ -1,8 +1,6 @@ // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. - -#if PYTHON36 using System; using System.Collections; using System.Collections.Specialized; @@ -13,24 +11,8 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + internal class TypeOffset36 { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; @@ -145,5 +127,3 @@ public static int magic() public static int members = 0; } } - -#endif diff --git a/src/runtime/interop37.cs b/src/runtime/interop37.cs index d5fc76ad3..c817f7a9b 100644 --- a/src/runtime/interop37.cs +++ b/src/runtime/interop37.cs @@ -1,8 +1,6 @@ // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. - -#if PYTHON37 using System; using System.Collections; using System.Collections.Specialized; @@ -13,24 +11,8 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + internal class TypeOffset37 { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; @@ -145,5 +127,3 @@ public static int magic() public static int members = 0; } } - -#endif diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index c1b663d22..01487cf22 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -95,10 +95,6 @@ public static string PythonPath } set { - if (Runtime.IsPython2) - { - throw new NotSupportedException("Set PythonPath not supported on Python 2"); - } Marshal.FreeHGlobal(_pythonPath); _pythonPath = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); Runtime.Py_SetPath(_pythonPath); @@ -244,11 +240,7 @@ static void OnDomainUnload(object _, EventArgs __) /// CPython interpreter process - this bootstraps the managed runtime /// when it is imported by the CLR extension module. /// -#if PYTHON3 public static IntPtr InitExt() -#elif PYTHON2 - public static void InitExt() -#endif { try { @@ -288,14 +280,10 @@ public static void InitExt() catch (PythonException e) { e.Restore(); -#if PYTHON3 return IntPtr.Zero; -#endif } -#if PYTHON3 return Python.Runtime.ImportHook.GetCLRModule(); -#endif } /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 4b7025e23..222045737 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1,4 +1,6 @@ using System; +using System.Globalization; +using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Text; @@ -6,7 +8,6 @@ namespace Python.Runtime { - using System.IO; [SuppressUnmanagedCodeSecurity] internal static class NativeMethods @@ -151,6 +152,12 @@ internal static T Throw(Exception exception) /// public class Runtime { + static Runtime() { + lock (VerLock) { + UpdateVersionFields(); + } + } + // 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. @@ -163,66 +170,83 @@ public class Runtime // binary substitution of different Python.Runtime.dll builds in a target application. public static string pyversion => _pyversion; + /// + /// Two-character string, describing Python version (e.g. "36" for Python 3.6) + /// public static string pyver => _pyver; -#if PYTHON27 - internal const string _pyversion = "2.7"; - internal const string _pyver = "27"; -#elif PYTHON34 - internal const string _pyversion = "3.4"; - internal const string _pyver = "34"; -#elif PYTHON35 - internal const string _pyversion = "3.5"; - internal const string _pyver = "35"; -#elif PYTHON36 - internal const string _pyversion = "3.6"; - internal const string _pyver = "36"; -#elif PYTHON37 - internal const string _pyversion = "3.7"; - internal const string _pyver = "37"; -#else -#error You must define one of PYTHON34 to PYTHON37 or PYTHON27 -#endif + static readonly object VerLock = new object(); + static Version pythonVersion = new Version(3, 7); + public static Version PythonVersion { + get { + lock (VerLock) { + return pythonVersion; + } + } + set { + if (value == null) + throw new ArgumentNullException(nameof(Version)); -#if MONO_LINUX || MONO_OSX // Linux/macOS use dotted version string - internal const string dllBase = "python" + _pyversion; -#else // Windows - internal const string dllBase = "python" + _pyver; -#endif + lock (VerLock) { + pythonVersion = value; + UpdateVersionFields(); + } + } + } + + static void UpdateVersionFields() { + _pyversion = pythonVersion.ToString(2); + _pyver = string.Format(CultureInfo.InvariantCulture, + "{0}{1}", pythonVersion.Major, pythonVersion.Minor); + pyversionnumber = GetPyVersionNumber(); + } + + internal static string _pyversion { get; private set; } + internal static string _pyver { get; private set; } #if PYTHON_WITH_PYDEBUG - internal const string dllWithPyDebug = "d"; + const string dllWithPyDebug = "d"; #else - internal const string dllWithPyDebug = ""; + const string dllWithPyDebug = ""; #endif -#if PYTHON_WITH_PYMALLOC - internal const string dllWithPyMalloc = "m"; + + static readonly bool IsWindowsPlatform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + static string GetDefaultDllName() { +#if PYTHON_WITHOUT_ENABLE_SHARED && !NETSTANDARD + return "__Internal"; #else - internal const string dllWithPyMalloc = ""; + string dllBase = "python" + (IsWindowsPlatform ? _pyver : _pyversion); + string dllWithPyMalloc = IsWindowsPlatform ? "" : "m"; + return dllBase + dllWithPyDebug + dllWithPyMalloc; #endif + } - // C# compiler copies constants to the assemblies that references this library. - // We needs to replace all public constants to static readonly fields to allow - // binary substitution of different Python.Runtime.dll builds in a target application. + static string pythonDllOverride; - public static string PythonDLL { get; set; } = _PythonDll; + public static string PythonDLL { + get { return pythonDllOverride ?? GetDefaultDllName(); } + set { + if (value == null) + throw new ArgumentNullException(nameof(PythonDLL)); -#if PYTHON_WITHOUT_ENABLE_SHARED && !NETSTANDARD - internal const string _PythonDll = "__Internal"; -#else - internal const string _PythonDll = dllBase + dllWithPyDebug + dllWithPyMalloc; -#endif + pythonDllOverride = value; + } + } - public static readonly int pyversionnumber = Convert.ToInt32(_pyver); + static int GetPyVersionNumber() { + return PythonVersion.Major * 10 + PythonVersion.Minor;; + } + [Obsolete("Use PythonVersion instead")] + public static int pyversionnumber = GetPyVersionNumber(); // set to true when python is finalizing internal static object IsFinalizingLock = new object(); internal static bool IsFinalizing; - internal static bool Is32Bit = IntPtr.Size == 4; + internal static readonly bool Is32Bit = IntPtr.Size == 4; - // .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - internal static bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; + [Obsolete("Use IsWindowsPlatform")] + internal static readonly bool IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; /// /// Operating system type as reported by Python. @@ -286,9 +310,6 @@ public enum MachineType /// public static string MachineName { get; private set; } - internal static bool IsPython2 = pyversionnumber < 30; - internal static bool IsPython3 = pyversionnumber >= 30; - /// /// Encoding to use to convert Unicode to/from Managed to Native /// @@ -318,18 +339,9 @@ internal static void Initialize(bool initSigs = false) ClassDerivedObject.Reset(); TypeManager.Reset(); - IntPtr op; - IntPtr dict; - if (IsPython3) - { - op = PyImport_ImportModule("builtins"); - dict = PyObject_GetAttrString(op, "__dict__"); - } - else // Python2 - { - dict = PyImport_GetModuleDict(); - op = PyDict_GetItemString(dict, "__builtin__"); - } + IntPtr op = PyImport_ImportModule("builtins"); + IntPtr dict = PyObject_GetAttrString(op, "__dict__"); + PyNotImplemented = PyObject_GetAttrString(op, "NotImplemented"); PyBaseObjectType = PyObject_GetAttrString(op, "object"); @@ -354,9 +366,7 @@ internal static void Initialize(bool initSigs = false) PyWrapperDescriptorType = PyObject_Type(op); XDecref(op); -#if PYTHON3 XDecref(dict); -#endif op = PyString_FromString("string"); PyStringType = PyObject_Type(op); @@ -366,11 +376,9 @@ internal static void Initialize(bool initSigs = false) PyUnicodeType = PyObject_Type(op); XDecref(op); -#if PYTHON3 op = PyBytes_FromString("bytes"); PyBytesType = PyObject_Type(op); XDecref(op); -#endif op = PyTuple_New(0); PyTupleType = PyObject_Type(op); @@ -396,24 +404,8 @@ internal static void Initialize(bool initSigs = false) PyFloatType = PyObject_Type(op); XDecref(op); -#if PYTHON3 PyClassType = IntPtr.Zero; PyInstanceType = IntPtr.Zero; -#elif PYTHON2 - IntPtr s = PyString_FromString("_temp"); - IntPtr d = PyDict_New(); - - IntPtr c = PyClass_New(IntPtr.Zero, d, s); - PyClassType = PyObject_Type(c); - - IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); - PyInstanceType = PyObject_Type(i); - - XDecref(s); - XDecref(i); - XDecref(c); - XDecref(d); -#endif Error = new IntPtr(-1); @@ -425,12 +417,11 @@ internal static void Initialize(bool initSigs = false) } _PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dllLocal, "_PyObject_NextNotImplemented"); -#if !(MONO_LINUX || MONO_OSX) - if (dllLocal != IntPtr.Zero) + if (IsWindowsPlatform && dllLocal != IntPtr.Zero) { NativeMethods.FreeLibrary(dllLocal); } -#endif + // Initialize data about the platform we're running on. We need // this for the type manager and potentially other details. Must // happen after caching the python types, above. @@ -541,9 +532,7 @@ internal static int AtExit() internal static IntPtr PyNoneType; internal static IntPtr PyTypeType; -#if PYTHON3 internal static IntPtr PyBytesType; -#endif internal static IntPtr _PyObject_NextNotImplemented; internal static IntPtr PyNotImplemented; @@ -798,17 +787,12 @@ internal static unsafe long Refcount(IntPtr op) internal static IntPtr PyGILState_GetThisThreadState() => Delegates.PyGILState_GetThisThreadState(); -#if PYTHON3 - public static int Py_Main( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv ) => Delegates.Py_Main(argc, argv ); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - public static extern int Py_Main(int argc, string[] argv); -#endif + internal static void PyEval_InitThreads() => Delegates.PyEval_InitThreads(); @@ -949,11 +933,6 @@ internal static string PyObject_GetTypeName(IntPtr op) internal static bool PyObject_IsIterable(IntPtr pointer) { var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); -#if PYTHON2 - long tp_flags = Util.ReadCLong(ob_type, TypeOffset.tp_flags); - if ((tp_flags & TypeFlags.HaveIter) == 0) - return false; -#endif IntPtr tp_iter = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iter); return tp_iter != IntPtr.Zero; } @@ -994,8 +973,6 @@ internal static bool PyObject_IsIterable(IntPtr pointer) internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args) => Delegates.PyObject_CallObject(pointer, args); -#if PYTHON3 - 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) @@ -1022,10 +999,6 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) Exceptions.SetError(Exceptions.SystemError, "Error comparing objects"); return -1; } -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyObject_Compare(IntPtr value1, IntPtr value2); -#endif internal static int PyObject_IsInstance(IntPtr ob, IntPtr type) => Delegates.PyObject_IsInstance(ob, type); @@ -1059,13 +1032,8 @@ internal static long PyObject_Size(IntPtr pointer) internal static IntPtr PyObject_Str(IntPtr pointer) => Delegates.PyObject_Str(pointer); -#if PYTHON3 internal static IntPtr PyObject_Unicode(IntPtr pointer) => Delegates.PyObject_Unicode(pointer); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_Unicode(IntPtr pointer); -#endif internal static IntPtr PyObject_Dir(IntPtr pointer) => Delegates.PyObject_Dir(pointer); @@ -1075,13 +1043,8 @@ internal static long PyObject_Size(IntPtr pointer) // Python number API //==================================================================== -#if PYTHON3 internal static IntPtr PyNumber_Int(IntPtr ob) => Delegates.PyNumber_Int(ob); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyNumber_Int(IntPtr ob); -#endif internal static IntPtr PyNumber_Long(IntPtr ob) => Delegates.PyNumber_Long(ob); @@ -1114,28 +1077,12 @@ internal static IntPtr PyInt_FromInt64(long value) return PyInt_FromLong(v); } -#if PYTHON3 - private static IntPtr PyInt_FromLong(IntPtr value) => Delegates.PyInt_FromLong(value); - internal static int PyInt_AsLong(IntPtr value) => Delegates.PyInt_AsLong(value); - internal static IntPtr PyInt_FromString(string value, IntPtr end, int radix) => Delegates.PyInt_FromString(value, end, radix); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr PyInt_FromLong(IntPtr value); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyInt_AsLong(IntPtr value); - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyInt_GetMax(); -#endif internal static bool PyLong_Check(IntPtr ob) { @@ -1374,15 +1321,9 @@ internal static bool PyString_Check(IntPtr ob) internal static IntPtr PyString_FromString(string value) { -#if PYTHON3 return PyUnicode_FromKindAndData(UCS, value, value.Length); -#elif PYTHON2 - return PyString_FromStringAndSize(value, value.Length); -#endif } -#if PYTHON3 - internal static IntPtr PyBytes_FromString(string op) => Delegates.PyBytes_FromString(op); internal static long PyBytes_Size(IntPtr op) @@ -1390,7 +1331,6 @@ internal static long PyBytes_Size(IntPtr op) return (long) _PyBytes_Size(op); } - private static IntPtr _PyBytes_Size(IntPtr op) => Delegates._PyBytes_Size(op); internal static IntPtr PyBytes_AS_STRING(IntPtr ob) @@ -1403,46 +1343,25 @@ internal static IntPtr PyString_FromStringAndSize(string value, long size) return _PyString_FromStringAndSize(value, new IntPtr(size)); } - internal static IntPtr _PyString_FromStringAndSize( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, IntPtr size - ) => Delegates._PyString_FromStringAndSize(value, size -); + ) => Delegates._PyString_FromStringAndSize(value, size); internal static IntPtr PyUnicode_FromStringAndSize(IntPtr value, long size) { return PyUnicode_FromStringAndSize(value, new IntPtr(size)); } - private static IntPtr PyUnicode_FromStringAndSize(IntPtr value, IntPtr size) => Delegates.PyUnicode_FromStringAndSize(value, size); -#elif PYTHON2 - internal static IntPtr PyString_FromStringAndSize(string value, long size) - { - return PyString_FromStringAndSize(value, new IntPtr(size)); - } - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr PyString_FromStringAndSize(string value, IntPtr size); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyString_AsString(IntPtr op); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int PyString_Size(IntPtr pointer); -#endif internal static bool PyUnicode_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyUnicodeType; } -#if PYTHON3 - internal static IntPtr PyUnicode_FromObject(IntPtr ob) => Delegates.PyUnicode_FromObject(ob); - 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) @@ -1450,7 +1369,6 @@ internal static IntPtr PyUnicode_FromKindAndData(int kind, string s, long size) return PyUnicode_FromKindAndData(kind, s, new IntPtr(size)); } - private static IntPtr PyUnicode_FromKindAndData( int kind, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, @@ -1468,52 +1386,11 @@ internal static long PyUnicode_GetSize(IntPtr ob) return (long)_PyUnicode_GetSize(ob); } - private static IntPtr _PyUnicode_GetSize(IntPtr ob) => Delegates._PyUnicode_GetSize(ob); - internal static IntPtr PyUnicode_AsUnicode(IntPtr ob) => Delegates.PyUnicode_AsUnicode(ob); - internal static IntPtr PyUnicode_FromOrdinal(int c) => Delegates.PyUnicode_FromOrdinal(c); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "FromObject")] - internal static extern IntPtr PyUnicode_FromObject(IntPtr ob); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "FromEncodedObject")] - internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - - internal static IntPtr PyUnicode_FromUnicode(string s, long size) - { - return PyUnicode_FromUnicode(s, new IntPtr(size)); - } - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "FromUnicode")] - private static extern IntPtr PyUnicode_FromUnicode( - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, - IntPtr size - ); - - internal static long PyUnicode_GetSize(IntPtr ob) - { - return (long) _PyUnicode_GetSize(ob); - } - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "GetSize")] - internal static extern IntPtr _PyUnicode_GetSize(IntPtr ob); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "AsUnicode")] - internal static extern IntPtr PyUnicode_AsUnicode(IntPtr ob); - - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = PyUnicodeEntryPoint + "FromOrdinal")] - internal static extern IntPtr PyUnicode_FromOrdinal(int c); -#endif internal static IntPtr PyUnicode_FromString(string s) { @@ -1537,13 +1414,6 @@ internal static string GetManagedString(IntPtr op) { IntPtr type = PyObject_TYPE(op); -#if PYTHON2 // Python 3 strings are all Unicode - if (type == PyStringType) - { - return Marshal.PtrToStringAnsi(PyString_AsString(op), PyString_Size(op)); - } -#endif - if (type == PyUnicodeType) { IntPtr p = PyUnicode_AsUnicode(op); @@ -1756,11 +1626,6 @@ internal static long PyTuple_Size(IntPtr pointer) internal static bool PyIter_Check(IntPtr pointer) { var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); -#if PYTHON2 - long tp_flags = Util.ReadCLong(ob_type, TypeOffset.tp_flags); - if ((tp_flags & TypeFlags.HaveIter) == 0) - return false; -#endif IntPtr tp_iternext = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iternext); return tp_iternext != IntPtr.Zero && tp_iternext != _PyObject_NextNotImplemented; } @@ -1785,50 +1650,29 @@ internal static bool PyIter_Check(IntPtr pointer) internal static string PyModule_GetFilename(IntPtr module) => Delegates.PyModule_GetFilename(module); -#if PYTHON3 - internal static IntPtr PyModule_Create2(IntPtr module, int apiver) => Delegates.PyModule_Create2(module, apiver); -#endif - internal static IntPtr PyImport_Import(IntPtr name) => Delegates.PyImport_Import(name); - internal static IntPtr PyImport_ImportModule(string name) => Delegates.PyImport_ImportModule(name); - internal static IntPtr PyImport_ReloadModule(IntPtr module) => Delegates.PyImport_ReloadModule(module); - internal static IntPtr PyImport_AddModule(string name) => Delegates.PyImport_AddModule(name); - internal static IntPtr PyImport_GetModuleDict() => Delegates.PyImport_GetModuleDict(); -#if PYTHON3 - internal static void PySys_SetArgvEx( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, int updatepath ) => Delegates.PySys_SetArgvEx(argc, argv, updatepath ); -#elif PYTHON2 - [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern void PySys_SetArgvEx( - int argc, - string[] argv, - int updatepath - ); -#endif - internal static IntPtr PySys_GetObject(string name) => Delegates.PySys_GetObject(name); - internal static int PySys_SetObject(string name, IntPtr ob) => Delegates.PySys_SetObject(name, ob); - //==================================================================== // Python type object API //==================================================================== @@ -1838,10 +1682,8 @@ internal static bool PyType_Check(IntPtr ob) return PyObject_TypeCheck(ob, PyTypeType); } - internal static void PyType_Modified(IntPtr type) => Delegates.PyType_Modified(type); - internal static bool PyType_IsSubtype(IntPtr t1, IntPtr t2) => Delegates.PyType_IsSubtype(t1, t2); internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) @@ -1850,7 +1692,6 @@ internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) return (t == tp) || PyType_IsSubtype(t, tp); } - 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) @@ -1858,34 +1699,24 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) return PyType_GenericAlloc(type, new IntPtr(n)); } - private static IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n) => Delegates.PyType_GenericAlloc(type, n); - internal static int PyType_Ready(IntPtr type) => Delegates.PyType_Ready(type); - internal static IntPtr _PyType_Lookup(IntPtr type, IntPtr name) => Delegates._PyType_Lookup(type, name); - internal static IntPtr PyObject_GenericGetAttr(IntPtr obj, IntPtr name) => Delegates.PyObject_GenericGetAttr(obj, name); - internal static int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value) => Delegates.PyObject_GenericSetAttr(obj, name, value); - internal static IntPtr _PyObject_GetDictPtr(IntPtr obj) => Delegates._PyObject_GetDictPtr(obj); - internal static void PyObject_GC_Del(IntPtr tp) => Delegates.PyObject_GC_Del(tp); - internal static void PyObject_GC_Track(IntPtr tp) => Delegates.PyObject_GC_Track(tp); - internal static void PyObject_GC_UnTrack(IntPtr tp) => Delegates.PyObject_GC_UnTrack(tp); - //==================================================================== // Python memory API //==================================================================== @@ -1895,7 +1726,6 @@ internal static IntPtr PyMem_Malloc(long size) return PyMem_Malloc(new IntPtr(size)); } - private static IntPtr PyMem_Malloc(IntPtr size) => Delegates.PyMem_Malloc(size); internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) @@ -1903,62 +1733,44 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) return PyMem_Realloc(ptr, new IntPtr(size)); } - private static IntPtr PyMem_Realloc(IntPtr ptr, IntPtr size) => Delegates.PyMem_Realloc(ptr, size); - internal static void PyMem_Free(IntPtr ptr) => Delegates.PyMem_Free(ptr); - //==================================================================== // Python exception API //==================================================================== - internal static void PyErr_SetString(IntPtr ob, string message) => Delegates.PyErr_SetString(ob, message); - internal static void PyErr_SetObject(IntPtr ob, IntPtr message) => Delegates.PyErr_SetObject(ob, message); - internal static IntPtr PyErr_SetFromErrno(IntPtr ob) => Delegates.PyErr_SetFromErrno(ob); - internal static void PyErr_SetNone(IntPtr ob) => Delegates.PyErr_SetNone(ob); - internal static int PyErr_ExceptionMatches(IntPtr exception) => Delegates.PyErr_ExceptionMatches(exception); - internal static int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val) => Delegates.PyErr_GivenExceptionMatches(ob, val); - internal static void PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_NormalizeException(ob, val, tb); - internal static IntPtr PyErr_Occurred() => Delegates.PyErr_Occurred(); - internal static void PyErr_Fetch(ref IntPtr ob, ref IntPtr val, ref IntPtr tb) => Delegates.PyErr_Fetch(ref ob, ref val, ref tb); - internal static void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_Restore(ob, val, tb); - internal static void PyErr_Clear() => Delegates.PyErr_Clear(); - internal static void PyErr_Print() => Delegates.PyErr_Print(); - //==================================================================== // Miscellaneous //==================================================================== - internal static IntPtr PyMethod_Self(IntPtr ob) => Delegates.PyMethod_Self(ob); - internal static IntPtr PyMethod_Function(IntPtr ob) => Delegates.PyMethod_Function(ob); public static class Delegates @@ -3308,7 +3120,6 @@ int updatepath // end of PY3 enum Py2 { } - } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index d19c8737f..60258379f 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -412,23 +412,16 @@ internal static IntPtr AllocateTypeObject(string name) // Cheat a little: we'll set tp_name to the internal char * of // the Python version of the type name - otherwise we'd have to // allocate the tp_name and would have no way to free it. -#if PYTHON3 // For python3 we leak two objects. One for the ASCII representation // required for tp_name, and another for the Unicode representation // for ht_name. IntPtr temp = Runtime.PyBytes_FromString(name); IntPtr raw = Runtime.PyBytes_AS_STRING(temp); temp = Runtime.PyUnicode_FromString(name); -#elif PYTHON2 - IntPtr temp = Runtime.PyString_FromString(name); - IntPtr raw = Runtime.PyString_AsString(temp); -#endif Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); Marshal.WriteIntPtr(type, TypeOffset.name, temp); -#if PYTHON3 Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); -#endif long ptr = type.ToInt64(); // 64-bit safe @@ -441,11 +434,7 @@ internal static IntPtr AllocateTypeObject(string name) temp = new IntPtr(ptr + TypeOffset.mp_length); Marshal.WriteIntPtr(type, TypeOffset.tp_as_mapping, temp); -#if PYTHON3 temp = new IntPtr(ptr + TypeOffset.bf_getbuffer); -#elif PYTHON2 - temp = new IntPtr(ptr + TypeOffset.bf_getreadbuffer); -#endif Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp); return type; } diff --git a/src/runtime/interop27.cs b/src/runtime/typeoffset.cs similarity index 81% rename from src/runtime/interop27.cs rename to src/runtime/typeoffset.cs index 4782e9d3b..792a9605e 100644 --- a/src/runtime/interop27.cs +++ b/src/runtime/typeoffset.cs @@ -1,14 +1,8 @@ -// Auto-generated by geninterop.py. -// DO NOT MODIFIY BY HAND. - - -#if PYTHON27 using System; using System.Collections; using System.Collections.Specialized; using System.Runtime.InteropServices; using System.Reflection; -using System.Text; namespace Python.Runtime { @@ -17,12 +11,18 @@ internal class TypeOffset { static TypeOffset() { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); + string versionedOffsetTypeName = typeof(TypeOffset).FullName + Runtime.pyver; + var versionedOffsetType = typeof(TypeOffset).Assembly.GetType(versionedOffsetTypeName); + if (versionedOffsetType == null) + throw new NotSupportedException("Python version is not supported"); + + FieldInfo[] fi = versionedOffsetType.GetFields(); + Type typeOffset = typeof(TypeOffset); int size = IntPtr.Size; for (int i = 0; i < fi.Length; i++) { fi[i].SetValue(null, i * size); + typeOffset.GetField(fi[i].Name).SetValue(null, i * size); } } @@ -31,7 +31,6 @@ public static int magic() return ob_size; } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; public static int ob_size = 0; @@ -42,7 +41,7 @@ public static int magic() public static int tp_print = 0; public static int tp_getattr = 0; public static int tp_setattr = 0; - public static int tp_compare = 0; + public static int tp_as_async = 0; public static int tp_repr = 0; public static int tp_as_number = 0; public static int tp_as_sequence = 0; @@ -81,33 +80,32 @@ public static int magic() public static int tp_weaklist = 0; public static int tp_del = 0; public static int tp_version_tag = 0; + public static int tp_finalize = 0; + public static int am_await = 0; + public static int am_aiter = 0; + public static int am_anext = 0; public static int nb_add = 0; public static int nb_subtract = 0; public static int nb_multiply = 0; - public static int nb_divide = 0; public static int nb_remainder = 0; public static int nb_divmod = 0; public static int nb_power = 0; public static int nb_negative = 0; public static int nb_positive = 0; public static int nb_absolute = 0; - public static int nb_nonzero = 0; + public static int nb_bool = 0; public static int nb_invert = 0; public static int nb_lshift = 0; public static int nb_rshift = 0; public static int nb_and = 0; public static int nb_xor = 0; public static int nb_or = 0; - public static int nb_coerce = 0; public static int nb_int = 0; - public static int nb_long = 0; + public static int nb_reserved = 0; public static int nb_float = 0; - public static int nb_oct = 0; - public static int nb_hex = 0; public static int nb_inplace_add = 0; public static int nb_inplace_subtract = 0; public static int nb_inplace_multiply = 0; - public static int nb_inplace_divide = 0; public static int nb_inplace_remainder = 0; public static int nb_inplace_power = 0; public static int nb_inplace_lshift = 0; @@ -120,6 +118,8 @@ public static int magic() public static int nb_inplace_floor_divide = 0; public static int nb_inplace_true_divide = 0; public static int nb_index = 0; + public static int nb_matrix_multiply = 0; + public static int nb_inplace_matrix_multiply = 0; public static int mp_length = 0; public static int mp_subscript = 0; public static int mp_ass_subscript = 0; @@ -127,24 +127,20 @@ public static int magic() public static int sq_concat = 0; public static int sq_repeat = 0; public static int sq_item = 0; - public static int sq_slice = 0; + public static int was_sq_slice = 0; public static int sq_ass_item = 0; - public static int sq_ass_slice = 0; + public static int was_sq_ass_slice = 0; public static int sq_contains = 0; public static int sq_inplace_concat = 0; public static int sq_inplace_repeat = 0; - public static int bf_getreadbuffer = 0; - public static int bf_getwritebuffer = 0; - public static int bf_getsegcount = 0; - public static int bf_getcharbuffer = 0; public static int bf_getbuffer = 0; public static int bf_releasebuffer = 0; public static int name = 0; public static int ht_slots = 0; + public static int qualname = 0; + public static int ht_cached_keys = 0; /* here are optional user slots, followed by the members. */ public static int members = 0; } } - -#endif diff --git a/src/testing/Python.Test.15.csproj b/src/testing/Python.Test.15.csproj index 79387ce7f..9522d9fe1 100644 --- a/src/testing/Python.Test.15.csproj +++ b/src/testing/Python.Test.15.csproj @@ -3,7 +3,6 @@ netstandard2.0 x64;x86 - DebugMono;DebugMonoPY3;ReleaseMono;ReleaseMonoPY3;DebugWin;DebugWinPY3;ReleaseWin;ReleaseWinPY3 Python.Test Python.Test Python.Test diff --git a/tools/geninterop/geninterop.py b/tools/geninterop/geninterop.py index f8ef8e561..f0c07bbc9 100644 --- a/tools/geninterop/geninterop.py +++ b/tools/geninterop/geninterop.py @@ -200,9 +200,7 @@ def preprocess_python_headers(): def gen_interop_code(members): """Generate the TypeOffset C# class""" - defines = [ - "PYTHON{0}{1}".format(PY_MAJOR, PY_MINOR) - ] + PY_VER = "{0}{1}".format(PY_MAJOR, PY_MINOR) if hasattr(sys, "abiflags"): if "d" in sys.abiflags: @@ -213,13 +211,10 @@ def gen_interop_code(members): defines.append("PYTHON_WITH_WIDE_UNICODE") filename = os.path.basename(__file__) - defines_str = " && ".join(defines) class_definition = """ -// Auto-generated by %s. +// Auto-generated by {0}. // DO NOT MODIFIY BY HAND. - -#if %s using System; using System.Collections; using System.Collections.Specialized; @@ -228,28 +223,12 @@ def gen_interop_code(members): using System.Text; namespace Python.Runtime -{ +{{ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset - { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - + internal class TypeOffset{1} + {{ // Auto-generated from PyHeapTypeObject in Python.h -""" % (filename, defines_str) +""".format(filename, PY_VER) # All the members are sizeof(void*) so we don't need to do any # extra work to determine the size based on the type. @@ -262,8 +241,6 @@ def gen_interop_code(members): public static int members = 0; } } - -#endif """ return class_definition From f4ac6e89249636fb89f99c0f8aa1f050b3fddda2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 13 Jun 2019 14:27:50 -0700 Subject: [PATCH 034/240] when looking for a custom argument converter look at base types too --- src/runtime/methodbinder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 4b654f8a9..3ed6e19ca 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -201,11 +201,11 @@ static PyArgConverterAttribute TryGetArgConverter(Type type) { return ArgConverterCache.GetOrAdd(type, declaringType => declaringType - .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: false) + .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: true) .OfType() .SingleOrDefault() ?? declaringType.Assembly - .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: false) + .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: true) .OfType() .SingleOrDefault() ); From 3bf2bded6c99395a554f6eb2cb9c2209f7324347 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 13 Jun 2019 14:30:01 -0700 Subject: [PATCH 035/240] a test to ensure it is possible to override argument conversion for inherited methods using an attribute on a derived class --- src/embed_tests/TestCustomArgMarshal.cs | 33 +++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 9bb8ae7f3..7ef24490c 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -28,14 +28,28 @@ public void CustomArgMarshaller() } Assert.AreEqual(expected: 42, actual: obj.LastArgument); } + + [Test] + public void MarshallerOverride() { + var obj = new DerivedMarshaling(); + using (Py.GIL()) { + dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallWithInt({ 'value': 42 })"); + callWithInt(obj.ToPython()); + } + Assert.AreEqual(expected: 42, actual: obj.LastArgument); + } } [PyArgConverter(typeof(CustomArgConverter))] class CustomArgMarshaling { - public object LastArgument { get; private set; } - public void CallWithInt(int value) => this.LastArgument = value; + public object LastArgument { get; protected set; } + public virtual void CallWithInt(int value) => this.LastArgument = value; } + // this should override original custom marshaling behavior + [PyArgConverter(typeof(CustomArgConverter2))] + class DerivedMarshaling: CustomArgMarshaling { } + class CustomArgConverter : DefaultPyArgumentConverter { public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, out object arg, out bool isOut) { @@ -50,4 +64,19 @@ public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool n return true; } } + + class CustomArgConverter2 : DefaultPyArgumentConverter { + public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, + out object arg, out bool isOut) { + if (parameterType != typeof(int)) + return base.TryConvertArgument(pyarg, parameterType, needsResolution, out arg, out isOut); + bool isPyObject = base.TryConvertArgument(pyarg, typeof(PyObject), needsResolution, + out arg, out isOut); + if (!isPyObject) return false; + var dict = new PyDict((PyObject)arg); + int number = (dynamic)dict["value"]; + arg = number; + return true; + } + } } From 9bc5feb0831786c21ceee93a4c7d102b3a157be5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 18 Jun 2019 14:14:04 -0700 Subject: [PATCH 036/240] added IsInstance faking test --- src/embed_tests/Inheritance.cs | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/embed_tests/Inheritance.cs diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs new file mode 100644 index 000000000..cbb6d0361 --- /dev/null +++ b/src/embed_tests/Inheritance.cs @@ -0,0 +1,37 @@ +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + public class Inheritance { + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + [Test] + public void IsInstance() { + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + scope.Exec(AWrapper.Source); + var inheritedFromA = new InheritedFromA(); + dynamic isinstanceA = scope.Eval("lambda o: isinstance(o, A)"); + bool isA = isinstanceA(inheritedFromA); + Assert.IsTrue(isA); + } + } + } + + class PythonWrapperBase { } + + class AWrapper : PythonWrapperBase { + public const string Source = "class A: pass"; + } + + class InheritedFromA : AWrapper { + } +} From 9c00e9ad80388c4362c91a98cdb3df5375a34ba2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 19 Jun 2019 16:26:39 -0700 Subject: [PATCH 037/240] added an ability to override base types for C# objects when seen from Python To override base type, inherit from BaseTypeAttributeBase, and override BaseType method, that will assign python base types to C# classes. TypeManager will search for these attributes when a Python wrapper for a type is created, and set the Python base type correspondingly. --- src/embed_tests/Inheritance.cs | 70 ++++++++++++++++++++++---- src/runtime/BaseTypeAttributeBase.cs | 18 +++++++ src/runtime/PythonReferenceComparer.cs | 20 ++++++++ src/runtime/typemanager.cs | 38 +++++++++----- 4 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 src/runtime/BaseTypeAttributeBase.cs create mode 100644 src/runtime/PythonReferenceComparer.cs diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index cbb6d0361..e6cf66b35 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -1,3 +1,5 @@ +using System; + using NUnit.Framework; using Python.Runtime; @@ -6,6 +8,11 @@ public class Inheritance { [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); + using (Py.GIL()) { + var locals = new PyDict(); + PythonEngine.Exec(InheritanceTestBaseClassWrapper.ClassSourceCode, locals: locals.Handle); + CustomBaseTypeAttribute.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + } } [OneTimeTearDown] @@ -15,23 +22,68 @@ public void Dispose() { [Test] public void IsInstance() { + using (Py.GIL()) { + var inherited = new Inherited(); + bool properlyInherited = PyIsInstance(inherited, CustomBaseTypeAttribute.BaseClass); + Assert.IsTrue(properlyInherited); + } + } + + static dynamic PyIsInstance => PythonEngine.Eval("isinstance"); + + [Test] + public void InheritedClassIsNew() { + using (Py.GIL()) { + PyObject a = CustomBaseTypeAttribute.BaseClass; + var inherited = new Inherited(); + dynamic getClass = PythonEngine.Eval("lambda o: o.__class__"); + PyObject inheritedClass = getClass(inherited); + Assert.IsFalse(PythonReferenceComparer.Instance.Equals(a, inheritedClass)); + } + } + + [Test] + public void InheritedFromInheritedClassIsSelf() { using (Py.GIL()) using (var scope = Py.CreateScope()) { - scope.Exec(AWrapper.Source); - var inheritedFromA = new InheritedFromA(); - dynamic isinstanceA = scope.Eval("lambda o: isinstance(o, A)"); - bool isA = isinstanceA(inheritedFromA); - Assert.IsTrue(isA); + scope.Exec($"from {typeof(Inherited).Namespace} import {nameof(Inherited)}"); + scope.Exec($"class B({nameof(Inherited)}): pass"); + PyObject b = scope.Eval("B"); + PyObject bInst = ((dynamic)b)(scope); + dynamic getClass = scope.Eval("lambda o: o.__class__"); + PyObject inheritedClass = getClass(bInst); + Assert.IsTrue(PythonReferenceComparer.Instance.Equals(b, inheritedClass)); } } + + [Test] + public void InheritedFromInheritedIsInstance() { + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + scope.Exec($"from {typeof(Inherited).Namespace} import {nameof(Inherited)}"); + scope.Exec($"class B({nameof(Inherited)}): pass"); + PyObject b = scope.Eval("B"); + PyObject bInst = ((dynamic)b)(scope); + bool properlyInherited = PyIsInstance(bInst, CustomBaseTypeAttribute.BaseClass); + Assert.IsTrue(properlyInherited); + } + } + } + + class CustomBaseTypeAttribute : BaseTypeAttributeBase { + internal static PyObject BaseClass; + public override IntPtr BaseType(Type type) + => type != typeof(InheritanceTestBaseClassWrapper) ? IntPtr.Zero : BaseClass.Handle; } - class PythonWrapperBase { } + public class PythonWrapperBase { } - class AWrapper : PythonWrapperBase { - public const string Source = "class A: pass"; + [CustomBaseType] + public class InheritanceTestBaseClassWrapper : PythonWrapperBase { + public const string ClassName = "InheritanceTestBaseClass"; + public const string ClassSourceCode = "class " + ClassName + ": pass\n" + ClassName + " = " + ClassName + "\n"; } - class InheritedFromA : AWrapper { + public class Inherited : InheritanceTestBaseClassWrapper { } } diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs new file mode 100644 index 000000000..e9bec06e2 --- /dev/null +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -0,0 +1,18 @@ +using System; + +namespace Python.Runtime +{ + /// + /// Base class for all attributes, that override base type for C# classes as seen from Python + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum + | AttributeTargets.Interface | AttributeTargets.Struct)] + public abstract class BaseTypeAttributeBase : Attribute + { + /// + /// Get the handle of a Python type, that should be presented to Python as the base type + /// for the specified .NET type. + /// + public abstract IntPtr BaseType(Type type); + } +} diff --git a/src/runtime/PythonReferenceComparer.cs b/src/runtime/PythonReferenceComparer.cs new file mode 100644 index 000000000..d1ef9611f --- /dev/null +++ b/src/runtime/PythonReferenceComparer.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Python.Runtime { + /// + /// Compares Python object wrappers by Python object references. + /// Similar to but for Python objects + /// + public sealed class PythonReferenceComparer : IEqualityComparer + { + public static PythonReferenceComparer Instance { get; } = new PythonReferenceComparer(); + public bool Equals(PyObject x, PyObject y) + { + return x?.Handle == y?.Handle; + } + + public int GetHashCode(PyObject obj) => obj.Handle.GetHashCode(); + + private PythonReferenceComparer() { } + } +} diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 60258379f..809716dcb 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -1,6 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -119,7 +119,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) name = name.Substring(i + 1); } - IntPtr base_ = IntPtr.Zero; int ob_size = ObjectOffset.Size(Runtime.PyTypeType); int tp_dictoffset = ObjectOffset.DictOffset(Runtime.PyTypeType); @@ -132,16 +131,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) tp_dictoffset = ObjectOffset.DictOffset(Exceptions.Exception); } - if (clrType == typeof(Exception)) - { - base_ = Exceptions.Exception; - } - else if (clrType.BaseType != null) - { - ClassBase bc = ClassManager.GetClass(clrType.BaseType); - base_ = bc.pyHandle; - } - IntPtr type = AllocateTypeObject(name); Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); @@ -153,6 +142,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlots(type, impl.GetType()); + IntPtr base_ = GetBaseType(clrType); if (base_ != IntPtr.Zero) { Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); @@ -191,6 +181,30 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return type; } + static IntPtr GetBaseType(Type clrType) { + var baseTypeOverride = clrType.GetCustomAttributes(inherit: false) + .OfType().SingleOrDefault(); + if (baseTypeOverride != null) + { + IntPtr handle = baseTypeOverride.BaseType(clrType); + if (handle != IntPtr.Zero) + { + return handle; + } + } + if (clrType == typeof(Exception)) + { + return Exceptions.Exception; + } + if (clrType.BaseType != null) + { + ClassBase bc = ClassManager.GetClass(clrType.BaseType); + return bc.pyHandle; + } + + return IntPtr.Zero; + } + internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) { // Utility to create a subtype of a managed type with the ability for the From ecf99cdea31527f43ee9cd1a9c3de4f7d6abf3a3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 19 Jun 2019 16:27:48 -0700 Subject: [PATCH 038/240] set some repository-specific style options --- .editorconfig | 5 +++++ src/embed_tests/TestInstanceWrapping.cs | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 525ffcde1..85eb7e5a2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -30,3 +30,8 @@ indent_style = tab [*.cs] csharp_new_line_before_open_brace = true +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true + +csharp_prefer_braces = true:suggestion diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index ca5386366..0e9cf26f0 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -1,11 +1,9 @@ -using System; +using System.Globalization; using NUnit.Framework; using Python.Runtime; namespace Python.EmbeddingTest { - using System.Globalization; - public class TestInstanceWrapping { [OneTimeSetUp] public void SetUp() { From 0f395537ed46e75dcca72051bc284c4681fa36ee Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 20 Jun 2019 12:37:18 -0700 Subject: [PATCH 039/240] fixed MarshallerOverride test --- src/embed_tests/TestCustomArgMarshal.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 7ef24490c..7c084d7f5 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -46,9 +46,13 @@ class CustomArgMarshaling { public virtual void CallWithInt(int value) => this.LastArgument = value; } - // this should override original custom marshaling behavior + // this should override original custom marshaling behavior for any new methods [PyArgConverter(typeof(CustomArgConverter2))] - class DerivedMarshaling: CustomArgMarshaling { } + class DerivedMarshaling : CustomArgMarshaling { + public override void CallWithInt(int value) { + base.CallWithInt(value); + } + } class CustomArgConverter : DefaultPyArgumentConverter { public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, From 805f92b28840b447a60266139d3ba6f4917f318f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 20 Jun 2019 13:14:24 -0700 Subject: [PATCH 040/240] added a test, that ensures C# classes with public instance __call__ method are callable in Python #890 --- src/embed_tests/CallableObject.cs | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/embed_tests/CallableObject.cs diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs new file mode 100644 index 000000000..e68e13d87 --- /dev/null +++ b/src/embed_tests/CallableObject.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + class CallableObject { + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + [Test] + public void CallMethodMakesObjectCallable() { + var doubler = new Doubler(); + using (Py.GIL()) { + dynamic applyObjectTo21 = PythonEngine.Eval("lambda o: o(21)"); + Assert.AreEqual(doubler.__call__(21), (int)applyObjectTo21(doubler.ToPython())); + } + } + + class Doubler { + public int __call__(int arg) => 2 * arg; + } + } +} From d46878c75acd0c2b177b9c2f5670d31727a844fa Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 20 Jun 2019 13:53:20 -0700 Subject: [PATCH 041/240] make .NET classes, that have __call__ method callable from Python #890 --- src/runtime/Python.Runtime.15.csproj | 2 +- src/runtime/classobject.cs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index a0186916c..8fdaeb339 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -19,7 +19,7 @@ ..\..\ $(SolutionDir)\bin\ $(PythonBuildDir)\$(TargetFramework)\ - 6 + 7.3 True ..\pythonnet.snk $(PYTHONNET_DEFINE_CONSTANTS) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 83d761fd0..7427b40cb 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -1,5 +1,6 @@ using System; using System.Reflection; +using System.Runtime.InteropServices; namespace Python.Runtime { @@ -294,7 +295,20 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) if (cb.type != typeof(Delegate)) { - Exceptions.SetError(Exceptions.TypeError, "object is not callable"); + IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict); + IntPtr methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); + if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) + { + Exceptions.SetError(Exceptions.TypeError, "object is not callable"); + return IntPtr.Zero; + } + + if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) + { + return methodObject.Invoke(ob, args, kw); + } + + Exceptions.SetError(Exceptions.TypeError, "instance has __call__, but it is not supported by Python.NET"); return IntPtr.Zero; } From 960457f5ef22865216a4d6ff4c96073d110765aa Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 24 Jun 2019 15:11:03 -0700 Subject: [PATCH 042/240] C# classes, which inherited __call__ from their Python base class, are also callable now A test case added to CallableObject.cs When tp_call is invoked for a custom .NET class, and __call__ is not implemented in .NET, walk the class hierarchy (as seen from Python) until Python class is found. Then try to invoke its __call__ method, if defined. #890 --- src/embed_tests/CallableObject.cs | 32 +++++++++++++++++ src/runtime/classobject.cs | 57 ++++++++++++++++++++++++++++--- src/runtime/managedtype.cs | 20 ----------- src/runtime/runtime.cs | 12 +++++++ 4 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index e68e13d87..c1d358faf 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -9,6 +9,11 @@ class CallableObject { [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); + using (Py.GIL()) { + var locals = new PyDict(); + PythonEngine.Exec(CallViaInheritance.BaseClassSource, locals: locals.Handle); + CustomBaseTypeAttribute.BaseClass = locals[CallViaInheritance.BaseClassName]; + } } [OneTimeTearDown] @@ -25,8 +30,35 @@ public void CallMethodMakesObjectCallable() { } } + [Test] + public void CallMethodCanBeInheritedFromPython() { + var callViaInheritance = new CallViaInheritance(); + using (Py.GIL()) { + dynamic applyObjectTo14 = PythonEngine.Eval("lambda o: o(14)"); + Assert.AreEqual(callViaInheritance.Call(14), (int)applyObjectTo14(callViaInheritance.ToPython())); + } + } + class Doubler { public int __call__(int arg) => 2 * arg; } + + [CustomBaseType] + class CallViaInheritance { + public const string BaseClassName = "Forwarder"; + public static readonly string BaseClassSource = $@" +class {BaseClassName}: + def __call__(self, val): + return self.Call(val) +"; + public int Call(int arg) => 3 * arg; + } + + class CustomBaseTypeAttribute : BaseTypeAttributeBase { + internal static PyObject BaseClass; + + public override IntPtr BaseType(Type type) + => type != typeof(CallViaInheritance) ? IntPtr.Zero : BaseClass.Handle; + } } } diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 7427b40cb..3fb7fd70a 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; @@ -299,17 +300,44 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) IntPtr methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) { + Runtime.XDecrefIgnoreNull(methodObjectHandle); Exceptions.SetError(Exceptions.TypeError, "object is not callable"); return IntPtr.Zero; } - if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) + try { - return methodObject.Invoke(ob, args, kw); + if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) + { + return methodObject.Invoke(ob, args, kw); + } + + IntPtr pythonBase = GetPythonBase(tp); + dict = Marshal.ReadIntPtr(pythonBase, TypeOffset.tp_dict); + Runtime.XDecref(methodObjectHandle); + methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); + if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) + { + Exceptions.SetError(Exceptions.TypeError, "object is not callable"); + return IntPtr.Zero; + } + + var boundMethod = Runtime.PyMethod_New(methodObjectHandle, ob); + if (boundMethod == IntPtr.Zero) { return IntPtr.Zero; } + + try + { + return Runtime.PyObject_Call(boundMethod, args, kw); + } + finally + { + Runtime.XDecref(boundMethod); + } + } + finally + { + Runtime.XDecrefIgnoreNull(methodObjectHandle); } - - Exceptions.SetError(Exceptions.TypeError, "instance has __call__, but it is not supported by Python.NET"); - return IntPtr.Zero; } var co = (CLRObject)GetManagedObject(ob); @@ -323,5 +351,24 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) var binder = new MethodBinder(method); return binder.Invoke(ob, args, kw); } + + /// + /// Get the first base class in the class hierarchy + /// of the specified .NET type, that is defined in Python. + /// + static IntPtr GetPythonBase(IntPtr tp) { + Debug.Assert(IsManagedType(tp)); + do { + tp = Marshal.ReadIntPtr(tp, TypeOffset.tp_base); + } while (IsManagedType(tp)); + + return tp; + } + + internal static bool IsManagedType(IntPtr tp) + { + var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); + return (flags & TypeFlags.Managed) != 0; + } } } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 3191da949..c59ead405 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -55,25 +55,5 @@ internal static ManagedType GetManagedObjectErr(IntPtr ob) } return result; } - - - internal static bool IsManagedType(IntPtr ob) - { - if (ob != IntPtr.Zero) - { - IntPtr tp = Runtime.PyObject_TYPE(ob); - if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) - { - tp = ob; - } - - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Managed) != 0) - { - return true; - } - } - return false; - } } } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 222045737..d62e3f4f4 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -715,6 +715,10 @@ internal static unsafe void XDecref(IntPtr op) #endif } + internal static void XDecrefIgnoreNull(IntPtr op) { + if (op != IntPtr.Zero) { XDecref(op); } + } + internal static unsafe long Refcount(IntPtr op) { var p = (void*)op; @@ -1773,6 +1777,8 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) internal static IntPtr PyMethod_Function(IntPtr ob) => Delegates.PyMethod_Function(ob); + internal static IntPtr PyMethod_New(IntPtr func, IntPtr self) => Delegates.PyMethod_New(func, self); + public static class Delegates { static Delegates() @@ -1993,6 +1999,7 @@ static Delegates() PyErr_Print = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyErr_Print), GetUnmanagedDll(PythonDLL))); PyMethod_Self = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Self), GetUnmanagedDll(PythonDLL))); PyMethod_Function = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_Function), GetUnmanagedDll(PythonDLL))); + PyMethod_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_New), GetUnmanagedDll(PythonDLL))); } static T GetDelegateForFunctionPointer(IntPtr functionPointer) { @@ -3117,6 +3124,11 @@ int updatepath [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate IntPtr PyMethod_FunctionDelegate(IntPtr ob); + + internal static PyMethod_NewDelegate PyMethod_New { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate IntPtr PyMethod_NewDelegate(IntPtr func, IntPtr self); // end of PY3 enum Py2 { } From e797f7f6b25ea84cfd87e24594d838047629d9b4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 24 Jun 2019 16:40:56 -0700 Subject: [PATCH 043/240] Populate InnerException from Python's __cause__ when available This change only affects some exception handling, but not all of it. Instead, parameterless PythonException constructor is made Obsolete. PythonException.FromPyErr() should be called instead. FromPyErr will check __cause__, and, if present, parse it into InnerException property. This change will cause a slowdown, as I found no way to read __cause__ on demand, because InnerException is not virtual. This addresses #893 --- src/embed_tests/TestPythonException.cs | 16 ++++++ src/runtime/pyobject.cs | 1 + src/runtime/pythonexception.cs | 79 +++++++++++++++++++++++++- src/runtime/runtime.cs | 2 +- 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/TestPythonException.cs b/src/embed_tests/TestPythonException.cs index 57a8d54af..89d4776f8 100644 --- a/src/embed_tests/TestPythonException.cs +++ b/src/embed_tests/TestPythonException.cs @@ -54,5 +54,21 @@ public void TestPythonErrorTypeName() Assert.That(ex.PythonTypeName, Is.EqualTo("ModuleNotFoundError").Or.EqualTo("ImportError")); } } + + [Test] + public void TestNestedExceptions() + { + try { + PythonEngine.Exec(@" +try: + raise Exception('inner') +except Exception as ex: + raise Exception('outer') from ex +"); + } catch (PythonException ex) { + Assert.That(ex.InnerException, Is.InstanceOf()); + Assert.That(ex.InnerException.Message, Is.EqualTo("Exception : inner")); + } + } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 3b8c71efa..c6f3914f8 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -156,6 +156,7 @@ public void Dispose() GC.SuppressFinalize(this); } + internal IntPtr GetPythonTypeHandle() => Runtime.PyObject_Type(obj); /// /// GetPythonType Method diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index ded7fbeb5..5a475c9b9 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -11,11 +11,12 @@ public class PythonException : System.Exception private IntPtr _pyType = IntPtr.Zero; private IntPtr _pyValue = IntPtr.Zero; private IntPtr _pyTB = IntPtr.Zero; - private string _tb = ""; + private string _traceback = ""; private string _message = ""; private string _pythonTypeName = ""; private bool disposed = false; + [Obsolete("Please, use FromPyErr instead")] public PythonException() { IntPtr gs = PythonEngine.AcquireLock(); @@ -49,12 +50,84 @@ public PythonException() Runtime.XIncref(_pyTB); using (var pyTB = new PyObject(_pyTB)) { - _tb = tb_module.InvokeMethod("format_tb", pyTB).ToString(); + this._traceback = tb_module.InvokeMethod("format_tb", pyTB).ToString(); } } PythonEngine.ReleaseLock(gs); } + private PythonException(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle, + string message, string pythonTypeName, string traceback, + Exception innerException) + : base(message, innerException) + { + _pyType = pyTypeHandle; + _pyValue = pyValueHandle; + _pyTB = pyTracebackHandle; + _message = message; + _pythonTypeName = pythonTypeName ?? _pythonTypeName; + _traceback = traceback ?? _traceback; + } + + internal static PythonException FromPyErr() { + IntPtr gs = PythonEngine.AcquireLock(); + IntPtr pyTypeHandle = IntPtr.Zero, pyValueHandle = IntPtr.Zero, pyTracebackHandle = IntPtr.Zero; + Runtime.PyErr_Fetch(ref pyTypeHandle, ref pyValueHandle, ref pyTracebackHandle); + Runtime.XIncref(pyTypeHandle); + Runtime.XIncref(pyValueHandle); + Runtime.XIncref(pyTracebackHandle); + var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); + PythonEngine.ReleaseLock(gs); + return result; + } + + /// + /// Requires lock to be acquired eslewhere + /// + static PythonException FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle) { + Exception inner = null; + string pythonTypeName = null, msg = "", traceback = null; + if (pyTypeHandle != IntPtr.Zero && pyValueHandle != IntPtr.Zero) + { + string type; + string message; + Runtime.XIncref(pyTypeHandle); + using (var pyType = new PyObject(pyTypeHandle)) + using (PyObject pyTypeName = pyType.GetAttr("__name__")) + { + type = pyTypeName.ToString(); + } + + pythonTypeName = type; + + Runtime.XIncref(pyValueHandle); + using (var pyValue = new PyObject(pyValueHandle)) + { + message = pyValue.ToString(); + var cause = pyValue.GetAttr("__cause__", null); + if (cause != null) { + IntPtr innerTraceback = cause.GetAttr("__traceback__", null)?.Handle ?? IntPtr.Zero; + Runtime.XIncref(innerTraceback); + inner = FromPyErr(cause.GetPythonTypeHandle(), cause.obj, innerTraceback); + Runtime.XDecref(innerTraceback); + } + } + msg = type + " : " + message; + } + if (pyTracebackHandle != IntPtr.Zero) + { + PyObject tb_module = PythonEngine.ImportModule("traceback"); + Runtime.XIncref(pyTracebackHandle); + using (var pyTB = new PyObject(pyTracebackHandle)) + { + traceback = tb_module.InvokeMethod("format_tb", pyTB).ToString(); + } + } + + return new PythonException(pyTypeHandle, pyValueHandle, pyTracebackHandle, + msg, pythonTypeName, traceback, inner); + } + // Ensure that encapsulated Python objects are decref'ed appropriately // when the managed exception wrapper is garbage-collected. @@ -132,7 +205,7 @@ public override string Message /// public override string StackTrace { - get { return _tb; } + get { return this._traceback; } } /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index d62e3f4f4..21f85c0b5 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -559,7 +559,7 @@ internal static void CheckExceptionOccurred() { if (PyErr_Occurred() != IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } From 35ac4ec4461dbf581edead48f49db54b04dfe3ca Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 24 Jun 2019 17:55:10 -0700 Subject: [PATCH 044/240] remove internal uses of PythonException parameterless constructor #893 --- src/embed_tests/TestPythonException.cs | 2 +- src/runtime/delegatemanager.cs | 2 +- src/runtime/exceptions.cs | 4 +- src/runtime/pydict.cs | 24 +++-------- src/runtime/pyiter.cs | 5 +-- src/runtime/pylist.cs | 20 +++------ src/runtime/pyobject.cs | 60 ++++++++------------------ src/runtime/pyscope.cs | 16 +++---- src/runtime/pysequence.cs | 12 +++--- src/runtime/pythonengine.cs | 2 +- 10 files changed, 51 insertions(+), 96 deletions(-) diff --git a/src/embed_tests/TestPythonException.cs b/src/embed_tests/TestPythonException.cs index 89d4776f8..627907531 100644 --- a/src/embed_tests/TestPythonException.cs +++ b/src/embed_tests/TestPythonException.cs @@ -37,7 +37,7 @@ public void TestMessage() [Test] public void TestNoError() { - var e = new PythonException(); // There is no PyErr to fetch + var e = PythonException.FromPyErr(); // There is no PyErr to fetch Assert.AreEqual("", e.Message); } diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 7632816d1..88a83ca28 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -248,7 +248,7 @@ public object TrueDispatch(ArrayList args) if (op == IntPtr.Zero) { - var e = new PythonException(); + var e = PythonException.FromPyErr(); throw e; } diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 13c841bca..5093a1fd8 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -172,7 +172,7 @@ internal static void ErrorCheck(IntPtr pointer) { if (pointer == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -183,7 +183,7 @@ internal static void ErrorOccurredCheck(IntPtr pointer) { if (pointer == IntPtr.Zero || ErrorOccurred()) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs index 7237d1990..4949f08fc 100644 --- a/src/runtime/pydict.cs +++ b/src/runtime/pydict.cs @@ -34,7 +34,7 @@ public PyDict() obj = Runtime.PyDict_New(); if (obj == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -106,10 +106,7 @@ public bool HasKey(string key) public PyObject Keys() { IntPtr items = Runtime.PyDict_Keys(obj); - if (items == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(items); return new PyObject(items); } @@ -123,10 +120,7 @@ public PyObject Keys() public PyObject Values() { IntPtr items = Runtime.PyDict_Values(obj); - if (items == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(items); return new PyObject(items); } @@ -140,10 +134,7 @@ public PyObject Values() public PyObject Items() { IntPtr items = Runtime.PyDict_Items(obj); - if (items == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(items); return new PyObject(items); } @@ -157,10 +148,7 @@ public PyObject Items() public PyDict Copy() { IntPtr op = Runtime.PyDict_Copy(obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(op); return new PyDict(op); } @@ -176,7 +164,7 @@ public void Update(PyObject other) int result = Runtime.PyDict_Update(obj, other.obj); if (result < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index ee07bcecf..c993e4895 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -34,10 +34,7 @@ public PyIter(IntPtr ptr) : base(ptr) public PyIter(PyObject iterable) { obj = Runtime.PyObject_GetIter(iterable.obj); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(obj); } protected override void Dispose(bool disposing) diff --git a/src/runtime/pylist.cs b/src/runtime/pylist.cs index b22d9d51f..93e885416 100644 --- a/src/runtime/pylist.cs +++ b/src/runtime/pylist.cs @@ -51,10 +51,7 @@ public PyList(PyObject o) public PyList() { obj = Runtime.PyList_New(0); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(obj); } @@ -75,7 +72,7 @@ public PyList(PyObject[] items) int r = Runtime.PyList_SetItem(obj, i, ptr); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } } @@ -104,10 +101,7 @@ public static bool IsListType(PyObject value) public static PyList AsList(PyObject value) { IntPtr op = Runtime.PySequence_List(value.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(op); return new PyList(op); } @@ -123,7 +117,7 @@ public void Append(PyObject item) int r = Runtime.PyList_Append(obj, item.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -138,7 +132,7 @@ public void Insert(int index, PyObject item) int r = Runtime.PyList_Insert(obj, index, item.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -154,7 +148,7 @@ public void Reverse() int r = Runtime.PyList_Reverse(obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -170,7 +164,7 @@ public void Sort() int r = Runtime.PyList_Sort(obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index c6f3914f8..59a9b2f56 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -220,10 +220,7 @@ public bool HasAttr(PyObject name) public PyObject GetAttr(string name) { IntPtr op = Runtime.PyObject_GetAttrString(obj, name); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(op); return new PyObject(op); } @@ -258,10 +255,7 @@ public PyObject GetAttr(string name, PyObject _default) public PyObject GetAttr(PyObject name) { IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(op); return new PyObject(op); } @@ -298,7 +292,7 @@ public void SetAttr(string name, PyObject value) int r = Runtime.PyObject_SetAttrString(obj, name, value.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -316,7 +310,7 @@ public void SetAttr(PyObject name, PyObject value) int r = Runtime.PyObject_SetAttr(obj, name.obj, value.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -333,7 +327,7 @@ public void DelAttr(string name) int r = Runtime.PyObject_SetAttrString(obj, name, IntPtr.Zero); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -351,7 +345,7 @@ public void DelAttr(PyObject name) int r = Runtime.PyObject_SetAttr(obj, name.obj, IntPtr.Zero); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -369,7 +363,7 @@ public virtual PyObject GetItem(PyObject key) IntPtr op = Runtime.PyObject_GetItem(obj, key.obj); if (op == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return new PyObject(op); } @@ -422,7 +416,7 @@ public virtual void SetItem(PyObject key, PyObject value) int r = Runtime.PyObject_SetItem(obj, key.obj, value.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -474,7 +468,7 @@ public virtual void DelItem(PyObject key) int r = Runtime.PyObject_DelItem(obj, key.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -585,10 +579,7 @@ public virtual PyObject this[int index] public PyObject GetIterator() { IntPtr r = Runtime.PyObject_GetIter(obj); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -618,10 +609,7 @@ public PyObject Invoke(params PyObject[] args) var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, IntPtr.Zero); t.Dispose(); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -636,10 +624,7 @@ public PyObject Invoke(params PyObject[] args) public PyObject Invoke(PyTuple args) { IntPtr r = Runtime.PyObject_Call(obj, args.obj, IntPtr.Zero); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -656,10 +641,7 @@ public PyObject Invoke(PyObject[] args, PyDict kw) var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw != null ? kw.obj : IntPtr.Zero); t.Dispose(); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -674,10 +656,7 @@ public PyObject Invoke(PyObject[] args, PyDict kw) public PyObject Invoke(PyTuple args, PyDict kw) { IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw != null ? kw.obj : IntPtr.Zero); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -835,10 +814,7 @@ public bool IsTrue() public PyList Dir() { IntPtr r = Runtime.PyObject_Dir(obj); - if (r == IntPtr.Zero) - { - throw new PythonException(); - } + Exceptions.ErrorCheck(r); return new PyList(r); } @@ -895,7 +871,7 @@ public override bool Equals(object o) int r = Runtime.PyObject_Compare(obj, ((PyObject)o).obj); if (Exceptions.ErrorOccurred()) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return r == 0; } @@ -936,7 +912,7 @@ public override bool TrySetMember(SetMemberBinder binder, object value) int r = Runtime.PyObject_SetAttrString(obj, binder.Name, ptr); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } Runtime.XDecref(ptr); return true; @@ -1008,7 +984,7 @@ private static void AddArgument(IntPtr argtuple, int i, object target) if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index 8e6957855..7dca4db2f 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -185,7 +185,7 @@ public void ImportAll(PyScope scope) int result = Runtime.PyDict_Update(variables, scope.variables); if (result < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -205,7 +205,7 @@ public void ImportAll(PyObject module) int result = Runtime.PyDict_Update(variables, module_dict); if (result < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -220,7 +220,7 @@ public void ImportAll(PyDict dict) int result = Runtime.PyDict_Update(variables, dict.obj); if (result < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -321,7 +321,7 @@ private void Exec(string code, IntPtr _globals, IntPtr _locals) Runtime.CheckExceptionOccurred(); if (ptr != Runtime.PyNone) { - throw new PythonException(); + throw PythonException.FromPyErr(); } Runtime.XDecref(ptr); } @@ -348,7 +348,7 @@ private void Set(string name, IntPtr value) int r = Runtime.PyObject_SetItem(variables, pyKey.obj, value); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } } @@ -367,7 +367,7 @@ public void Remove(string name) int r = Runtime.PyObject_DelItem(variables, pyKey.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } } @@ -422,7 +422,7 @@ public bool TryGet(string name, out PyObject value) IntPtr op = Runtime.PyObject_GetItem(variables, pyKey.obj); if (op == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } if (op == Runtime.PyNone) { @@ -555,7 +555,7 @@ internal PyScope NewScope(string name) var module = Runtime.PyModule_New(name); if (module == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return new PyScope(module, this); } diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs index bfaee79a6..6899fb8cf 100644 --- a/src/runtime/pysequence.cs +++ b/src/runtime/pysequence.cs @@ -44,7 +44,7 @@ public PyObject GetSlice(int i1, int i2) IntPtr op = Runtime.PySequence_GetSlice(obj, i1, i2); if (op == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return new PyObject(op); } @@ -61,7 +61,7 @@ public void SetSlice(int i1, int i2, PyObject v) int r = Runtime.PySequence_SetSlice(obj, i1, i2, v.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -77,7 +77,7 @@ public void DelSlice(int i1, int i2) int r = Runtime.PySequence_DelSlice(obj, i1, i2); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } } @@ -113,7 +113,7 @@ public bool Contains(PyObject item) int r = Runtime.PySequence_Contains(obj, item.obj); if (r < 0) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return r != 0; } @@ -131,7 +131,7 @@ public PyObject Concat(PyObject other) IntPtr op = Runtime.PySequence_Concat(obj, other.obj); if (op == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return new PyObject(op); } @@ -149,7 +149,7 @@ public PyObject Repeat(int count) IntPtr op = Runtime.PySequence_Repeat(obj, count); if (op == IntPtr.Zero) { - throw new PythonException(); + throw PythonException.FromPyErr(); } return new PyObject(op); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 01487cf22..f44359af5 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -522,7 +522,7 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu PyObject result = RunString(code, globals, locals, RunFlagType.File); if (result.obj != Runtime.PyNone) { - throw new PythonException(); + throw PythonException.FromPyErr(); } result.Dispose(); } From 1f190eacf579bbd6080eaad6fc361ff7d977665e Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 25 Jun 2019 11:08:46 -0700 Subject: [PATCH 045/240] fixed InnerException with "None : NoneType" message #893 PythonException.FromPyErr was not properly handling __cause__ of None --- src/embed_tests/TestPythonException.cs | 11 +++++++++++ src/runtime/pythonexception.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/TestPythonException.cs b/src/embed_tests/TestPythonException.cs index 627907531..87b26fabd 100644 --- a/src/embed_tests/TestPythonException.cs +++ b/src/embed_tests/TestPythonException.cs @@ -70,5 +70,16 @@ raise Exception('outer') from ex Assert.That(ex.InnerException.Message, Is.EqualTo("Exception : inner")); } } + + [Test] + public void InnerIsEmptyWithNoCause() + { + var list = new PyList(); + PyObject foo = null; + + var ex = Assert.Throws(() => foo = list[0]); + + Assert.IsNull(ex.InnerException); + } } } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 5a475c9b9..44389a4a5 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -105,7 +105,7 @@ static PythonException FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntP { message = pyValue.ToString(); var cause = pyValue.GetAttr("__cause__", null); - if (cause != null) { + if (cause != null && cause.Handle != Runtime.PyNone) { IntPtr innerTraceback = cause.GetAttr("__traceback__", null)?.Handle ?? IntPtr.Zero; Runtime.XIncref(innerTraceback); inner = FromPyErr(cause.GetPythonTypeHandle(), cause.obj, innerTraceback); From a1ffba7950b36c51300cd4cffb53b0117896883b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 25 Jun 2019 11:50:19 -0700 Subject: [PATCH 046/240] test, that ensures .NET instance functions can be analyzed by Python inspect module --- src/embed_tests/Inspect.cs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/embed_tests/Inspect.cs diff --git a/src/embed_tests/Inspect.cs b/src/embed_tests/Inspect.cs new file mode 100644 index 000000000..ea0f28614 --- /dev/null +++ b/src/embed_tests/Inspect.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + public class Inspect { + [SetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [TearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + [Test] + public void BoundMethodsAreInspectable() { + var obj = new Class(); + using (var scope = Py.CreateScope()) { + scope.Import("inspect"); + scope.Set(nameof(obj), obj); + var spec = scope.Eval($"inspect.getfullargspec({nameof(obj)}.{nameof(Class.Method)})"); + } + } + + class Class { + public void Method() { } + } + } +} From e9ba06dc661bac70d8c73f7216b268d006f4a6fe Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 25 Jun 2019 12:40:31 -0700 Subject: [PATCH 047/240] implemented __signature__ on methodbinding --- src/embed_tests/Inspect.cs | 3 ++- src/runtime/methodbinding.cs | 45 ++++++++++++++++++++++++++++++++++++ src/runtime/runtime.cs | 4 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/Inspect.cs b/src/embed_tests/Inspect.cs index ea0f28614..07e8be9be 100644 --- a/src/embed_tests/Inspect.cs +++ b/src/embed_tests/Inspect.cs @@ -27,7 +27,8 @@ public void BoundMethodsAreInspectable() { } class Class { - public void Method() { } + public void Method(int a, int b = 10) { } + public void Method(int a, object b) { } } } } diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index f402f91f8..27987796d 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace Python.Runtime @@ -59,6 +60,47 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) return mb.pyHandle; } + PyObject Singature { + get { + var infos = this.info == null ? this.m.info : new[] {this.info}; + // this is a primitive version + // the overload with the maximum number of parameters should be used + var primary = infos.First(); + var primaryParameters = primary.GetParameters(); + PyObject signatureClass = Runtime.InspectModule.GetAttr("Signature"); + var primaryReturn = primary.ReturnParameter; + if (infos.Any(i => i.GetParameters().Length != primaryParameters.Length + || i.ReturnParameter?.ParameterType != primaryReturn?.ParameterType)) { + return signatureClass.Invoke(); + } + + var parameters = new PyList(); + var parameterClass = primaryParameters.Length > 0 ? Runtime.InspectModule.GetAttr("Parameter") : null; + var positionalOrKeyword = primaryParameters.Length > 0 ? parameterClass.GetAttr("POSITIONAL_OR_KEYWORD") : null; + for (int i = 0; i < primaryParameters.Length; i++) { + var parameter = primaryParameters[i]; + var alternatives = infos.Select(info => info.GetParameters()[i]); + var defaultValue = alternatives + .Select(alternative => alternative.DefaultValue != DBNull.Value ? alternative.DefaultValue.ToPython() : null) + .FirstOrDefault(v => v != null) ?? parameterClass.GetAttr("empty"); + + if (alternatives.Any(alternative => alternative.Name != parameter.Name)) { + return signatureClass.Invoke(); + } + + var args = new PyTuple(new []{ parameter.Name.ToPython(), positionalOrKeyword}); + var kw = new PyDict(); + if (defaultValue != null) { + kw["default"] = defaultValue; + } + var parameterInfo = parameterClass.Invoke(args: args, kw: kw); + parameters.Append(parameterInfo); + } + + // TODO: add return annotation + return signatureClass.Invoke(parameters); + } + } /// /// MethodBinding __getattribute__ implementation. @@ -85,6 +127,9 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) case "Overloads": var om = new OverloadMapper(self.m, self.target); return om.pyHandle; + case "__signature__": + var sig = self.Singature; + return sig.Handle; default: return Runtime.PyObject_GenericGetAttr(ob, key); } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 21f85c0b5..683c9443d 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -548,6 +548,10 @@ internal static int AtExit() internal static IntPtr PyNone; internal static IntPtr Error; + private static readonly Lazy inspect = + new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); + public static PyObject InspectModule => inspect.Value; + /// /// Check if any Python Exceptions occurred. /// If any exist throw new PythonException. From 6f85ed7aa4415943ea1d4c10d1aaadc3892cd503 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 25 Jun 2019 19:07:28 -0700 Subject: [PATCH 048/240] allow .NET classes to override __getattr__ and __setattr__ --- src/embed_tests/TestInstanceWrapping.cs | 38 +++++++++++++++++++- src/runtime/slots.cs | 47 +++++++++++++++++++++++++ src/runtime/typemanager.cs | 14 ++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/runtime/slots.cs diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 0e9cf26f0..2c2b0ebe0 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Python.Runtime; +using Python.Runtime.Slots; namespace Python.EmbeddingTest { public class TestInstanceWrapping { @@ -72,10 +73,35 @@ public void OverloadResolution_UnknownToObject() { } } + [Test] + public void GetAttrCanBeOverriden() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + dynamic getNonexistingAttr = PythonEngine.Eval("lambda o: o.non_existing_attr"); + string nonexistentAttrValue = getNonexistingAttr(o); + Assert.AreEqual(GetAttrFallbackValue, nonexistentAttrValue); + } + } + + [Test] + public void SetAttrCanBeOverriden() { + var overloaded = new Overloaded(); + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + var o = overloaded.ToPython(); + scope.Set(nameof(o), o); + scope.Exec($"{nameof(o)}.non_existing_attr = 42"); + Assert.AreEqual(42, overloaded.Value); + } + } + + const string GetAttrFallbackValue = "undefined"; + class Base {} class Derived: Base { } - class Overloaded: Derived + class Overloaded: Derived, IGetAttr, ISetAttr { public int Value { get; set; } public void IntOrStr(int arg) => this.Value = arg; @@ -91,6 +117,16 @@ public void IntOrStr(string arg) => public const int Derived = Base + 1; public void BaseOrDerived(Base _) => this.Value = Base; public void BaseOrDerived(Derived _) => this.Value = Derived; + + public bool TryGetAttr(string name, out PyObject value) { + value = GetAttrFallbackValue.ToPython(); + return true; + } + + public bool TrySetAttr(string name, PyObject value) { + this.Value = value.As(); + return true; + } } } } diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs new file mode 100644 index 000000000..69023903f --- /dev/null +++ b/src/runtime/slots.cs @@ -0,0 +1,47 @@ +using System; + +namespace Python.Runtime.Slots +{ + /// + /// Implement this interface to override Python's __getattr__ for your class + /// + public interface IGetAttr { + bool TryGetAttr(string name, out PyObject value); + } + + /// + /// Implement this interface to override Python's __setattr__ for your class + /// + public interface ISetAttr { + bool TrySetAttr(string name, PyObject value); + } + + static class SlotOverrides { + public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { + IntPtr genericResult = Runtime.PyObject_GenericGetAttr(ob, key); + if (genericResult != IntPtr.Zero || !Runtime.PyString_Check(key)) { + return genericResult; + } + + Exceptions.Clear(); + + var self = (IGetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; + string attr = Runtime.GetManagedString(key); + return self.TryGetAttr(attr, out var value) + ? value.Handle + : Runtime.PyObject_GenericGetAttr(ob, key); + } + + public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { + if (!Runtime.PyString_Check(key)) { + return Runtime.PyObject_GenericSetAttr(ob, key, val); + } + + var self = (ISetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; + string attr = Runtime.GetManagedString(key); + return self.TrySetAttr(attr, new PyObject(val)) + ? 0 + : Runtime.PyObject_GenericSetAttr(ob, key, val); + } + } +} diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 809716dcb..b926a62bc 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using Python.Runtime.Slots; namespace Python.Runtime { @@ -142,6 +143,14 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlots(type, impl.GetType()); + if (typeof(IGetAttr).IsAssignableFrom(clrType)) { + InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); + } + + if (typeof(ISetAttr).IsAssignableFrom(clrType)) { + InitializeSlot(type, TypeOffset.tp_setattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_setattro))); + } + IntPtr base_ = GetBaseType(clrType); if (base_ != IntPtr.Zero) { @@ -748,6 +757,11 @@ static void InitializeSlot(IntPtr type, IntPtr slot, string name) Marshal.WriteIntPtr(type, offset, slot); } + static void InitializeSlot(IntPtr type, int slotOffset, MethodInfo method) { + IntPtr thunk = Interop.GetThunk(method); + Marshal.WriteIntPtr(type, slotOffset, thunk); + } + /// /// Given a newly allocated Python type object and a managed Type that /// implements it, initialize any methods defined by the Type that need From eda1bf7cf5d772065072a4125530752eaa49046d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 26 Jun 2019 15:01:07 -0700 Subject: [PATCH 049/240] attempt to fix AccessViolationException potentially caused by IGetAttr/ISetAttr --- src/runtime/runtime.cs | 8 ++++++++ src/runtime/slots.cs | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 683c9443d..1394b15ec 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -682,6 +682,14 @@ internal static unsafe void XIncref(IntPtr op) #endif } + /// + /// Increase Python's ref counter for the given object, and return the object back. + /// + internal static IntPtr SelfIncRef(IntPtr op) { + XIncref(op); + return op; + } + internal static unsafe void XDecref(IntPtr op) { #if PYTHON_WITH_PYDEBUG || NETSTANDARD diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index 69023903f..85e35c299 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -28,7 +28,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (IGetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; string attr = Runtime.GetManagedString(key); return self.TryGetAttr(attr, out var value) - ? value.Handle + ? Runtime.SelfIncRef(value.Handle) : Runtime.PyObject_GenericGetAttr(ob, key); } @@ -39,7 +39,7 @@ public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { var self = (ISetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; string attr = Runtime.GetManagedString(key); - return self.TrySetAttr(attr, new PyObject(val)) + return self.TrySetAttr(attr, new PyObject(Runtime.SelfIncRef(val))) ? 0 : Runtime.PyObject_GenericSetAttr(ob, key, val); } From e527c79b8df6a1ac6d0ebb0ba2a338828510e65f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 1 Jul 2019 10:38:35 -0700 Subject: [PATCH 050/240] add instance (this/self) info to "No method matches given arguments" message --- src/embed_tests/TestCallbacks.cs | 31 +++++++++++++++++++++++++++++++ src/runtime/methodbinder.cs | 13 ++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index 157a34226..ced2952bc 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -52,5 +52,36 @@ public void TestNoOverloadException() { StringAssert.EndsWith("()", error.Message); } } + + [Test] + public void TestNoInstanceOverloadException() { + var instance = new FunctionContainer(); + using (Py.GIL()) { + dynamic callWith42 = PythonEngine.Eval($"lambda f: f.{nameof(FunctionContainer.Instance)}([42])"); + var error = Assert.Throws(() => callWith42(instance.ToPython())); + Assert.AreEqual("TypeError", error.PythonTypeName); + string expectedMessageEnd = + $"{nameof(FunctionContainer)}.{nameof(FunctionContainer.Instance)}: ()"; + StringAssert.EndsWith(expectedMessageEnd, error.Message); + } + } + + [Test] + public void TestNoStaticOverloadException() { + using (Py.GIL()) { + var type = ((dynamic)new FunctionContainer().ToPython()).__class__; + dynamic callWith42 = PythonEngine.Eval($"lambda t: t.{nameof(FunctionContainer.Static)}([42])"); + var error = Assert.Throws(() => callWith42(type)); + Assert.AreEqual("TypeError", error.PythonTypeName); + string expectedMessageEnd = + $"{nameof(FunctionContainer)}::{nameof(FunctionContainer.Static)}: ()"; + StringAssert.EndsWith(expectedMessageEnd, error.Message); + } + } + + class FunctionContainer { + public void Instance(int arg) { } + public static void Static(int arg) { } + } } } diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 3ed6e19ca..7a2a07099 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -512,9 +512,16 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i if (binding == null) { var value = new StringBuilder("No method matches given arguments"); - if (methodinfo != null && methodinfo.Length > 0) - { - value.Append($" for {methodinfo[0].Name}"); + if (methodinfo != null && methodinfo.Length > 0) { + value.Append(" for "); + if (inst != IntPtr.Zero && inst != Runtime.PyNone) { + value.Append(Runtime.PyObject_GetTypeName(inst)); + value.Append(methodinfo[0].IsStatic ? "::": "."); + } else { + value.Append(methodinfo[0].DeclaringType.Name); + value.Append("::"); + } + value.Append(methodinfo[0].Name); } long argCount = Runtime.PyTuple_Size(args); From ffeb426419100e018e2a6820ae959e5ea1987164 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 1 Jul 2019 15:48:42 -0700 Subject: [PATCH 051/240] improved Python name generation for generic types --- src/runtime/typemanager.cs | 68 +++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index b926a62bc..dfce536b0 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -107,18 +107,7 @@ internal static IntPtr CreateType(Type impl) internal static IntPtr CreateType(ManagedType impl, Type clrType) { - // Cleanup the type name to get rid of funny nested type names. - string name = "CLR." + clrType.FullName; - int i = name.LastIndexOf('+'); - if (i > -1) - { - name = name.Substring(i + 1); - } - i = name.LastIndexOf('.'); - if (i > -1) - { - name = name.Substring(i + 1); - } + string name = GetPythonTypeName(clrType); int ob_size = ObjectOffset.Size(Runtime.PyTypeType); int tp_dictoffset = ObjectOffset.DictOffset(Runtime.PyTypeType); @@ -190,6 +179,61 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return type; } + static string GetPythonTypeName(Type clrType) + { + var result = new System.Text.StringBuilder(); + GetPythonTypeName(clrType, target: result); + return result.ToString(); + } + + static void GetPythonTypeName(Type clrType, System.Text.StringBuilder target) + { + if (clrType.IsGenericType) + { + string fullName = clrType.GetGenericTypeDefinition().FullName; + int argCountIndex = fullName.LastIndexOf('`'); + string nonGenericFullName = fullName.Substring(0, argCountIndex); + string nonGenericName = CleanupFullName(nonGenericFullName); + target.Append(nonGenericName); + + var arguments = clrType.GetGenericArguments(); + target.Append('<'); + for (int argIndex = 0; argIndex < arguments.Length; argIndex++) + { + if (argIndex != 0) + { + target.Append(','); + } + GetPythonTypeName(arguments[argIndex], target); + } + target.Append('>'); + } + else + { + string name = CleanupFullName(clrType.FullName); + target.Append(name); + } + } + + static string CleanupFullName(string fullTypeName) + { + // Cleanup the type name to get rid of funny nested type names. + string name = "CLR." + fullTypeName; + int i = name.LastIndexOf('+'); + if (i > -1) + { + name = name.Substring(i + 1); + } + + i = name.LastIndexOf('.'); + if (i > -1) + { + name = name.Substring(i + 1); + } + + return name; + } + static IntPtr GetBaseType(Type clrType) { var baseTypeOverride = clrType.GetCustomAttributes(inherit: false) .OfType().SingleOrDefault(); From 5bd769efbd8476456bf7e686acbc79f529731404 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 22 Aug 2019 16:56:53 -0700 Subject: [PATCH 052/240] fixed crash in MethodBinder.Bind when MethodInfo to invoke is passed explicitly --- src/runtime/methodbinder.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 7a2a07099..b94be3f40 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; @@ -167,16 +168,16 @@ internal MethodBase[] GetMethods() // I'm sure this could be made more efficient. list.Sort(new MethodSorter()); methods = (MethodBase[])list.ToArray(typeof(MethodBase)); - pyArgumentConverter = this.GetArgumentConverter(); + pyArgumentConverter = GetArgumentConverter(this.methods); init = true; } return methods; } - IPyArgumentConverter GetArgumentConverter() { + static IPyArgumentConverter GetArgumentConverter(IEnumerable methods) { IPyArgumentConverter converter = null; Type converterType = null; - foreach (MethodBase method in this.methods) + foreach (MethodBase method in methods) { PyArgConverterAttribute attribute = TryGetArgConverter(method.DeclaringType); if (converterType == null) @@ -326,14 +327,17 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth MethodBase[] _methods = null; var pynargs = (int)Runtime.PyTuple_Size(args); var isGeneric = false; + IPyArgumentConverter argumentConverter; if (info != null) { _methods = new MethodBase[1]; _methods.SetValue(info, 0); + argumentConverter = GetArgumentConverter(_methods); } else { _methods = GetMethods(); + argumentConverter = this.pyArgumentConverter; } // TODO: Clean up @@ -351,7 +355,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; } var outs = 0; - var margs = this.TryConvertArguments(pi, paramsArray, args, pynargs, defaultArgList, + var margs = TryConvertArguments(pi, paramsArray, argumentConverter, args, pynargs, defaultArgList, needsResolution: _methods.Length > 1, outs: out outs); @@ -406,7 +410,8 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth /// true, if overloading resolution is required /// Returns number of output parameters /// An array of .NET arguments, that can be passed to a method. - object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, + static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, + IPyArgumentConverter argumentConverter, IntPtr args, int pyArgCount, ArrayList defaultArgList, bool needsResolution, @@ -436,7 +441,7 @@ object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, : Runtime.PyTuple_GetItem(args, paramIndex); bool isOut; - if (!this.pyArgumentConverter.TryConvertArgument( + if (!argumentConverter.TryConvertArgument( op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { From 85f19625ecdfa927b461b75a0787c9b84f211466 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 26 Aug 2019 14:33:00 -0700 Subject: [PATCH 053/240] specify severity for C# new-line style violations --- .editorconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index 85eb7e5a2..01789615c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,9 +29,9 @@ trim_trailing_whitespace = false indent_style = tab [*.cs] -csharp_new_line_before_open_brace = true -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true +csharp_new_line_before_open_brace = true:suggestion +csharp_new_line_before_else = true:suggestion +csharp_new_line_before_catch = true:suggestion +csharp_new_line_before_finally = true:suggestion csharp_prefer_braces = true:suggestion From d0f26a3e71a626e2bee216b8bfde108186acd296 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 26 Aug 2019 14:33:41 -0700 Subject: [PATCH 054/240] updated dependencies in Python.EmbeddingTest --- src/embed_tests/Python.EmbeddingTest.15.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index c7d247df7..8998e2794 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -1,8 +1,8 @@ - + - netcoreapp2.0 + netcoreapp2.0 x64;x86 Exe false @@ -76,10 +76,10 @@ - - - - + + + + From bf317e1c4c65376f11338ea6d03f92a095e1389d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 26 Aug 2019 14:38:05 -0700 Subject: [PATCH 055/240] run embedding tests under x64 by default --- pythonnet.15.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonnet.15.sln b/pythonnet.15.sln index 18787df5b..48b7ba717 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -30,8 +30,8 @@ Global {2759F4FF-716B-4828-916F-50FA86613DFC}.Release|Any CPU.Build.0 = Release|Any CPU {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.ActiveCfg = Debug|x64 {66B8D01A-9906-452A-B09E-BF75EA76468F}.Debug|Any CPU.Build.0 = Debug|x64 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = Release|x86 - {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = Release|x86 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.ActiveCfg = Release|x64 + {66B8D01A-9906-452A-B09E-BF75EA76468F}.Release|Any CPU.Build.0 = Release|x64 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.ActiveCfg = Debug|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Debug|Any CPU.Build.0 = Debug|x86 {E08678D4-9A52-4AD5-B63D-8EBC7399981B}.Release|Any CPU.ActiveCfg = Release|x86 From fe365540bae3efc999a9e937fad428240b2e6c41 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 26 Aug 2019 16:54:25 -0700 Subject: [PATCH 056/240] ensure base type override can be inherited --- src/embed_tests/Inheritance.cs | 7 ++++ src/runtime/BaseTypeAttributeBase.cs | 4 ++- src/runtime/typemanager.cs | 48 ++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index e6cf66b35..cd885fab7 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -70,12 +70,19 @@ public void InheritedFromInheritedIsInstance() { } } + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] class CustomBaseTypeAttribute : BaseTypeAttributeBase { internal static PyObject BaseClass; public override IntPtr BaseType(Type type) => type != typeof(InheritanceTestBaseClassWrapper) ? IntPtr.Zero : BaseClass.Handle; } + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + class DefaultBaseTypeAttribute : BaseTypeAttributeBase { + public override IntPtr BaseType(Type type) => IntPtr.Zero; + } + + [DefaultBaseType] public class PythonWrapperBase { } [CustomBaseType] diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs index e9bec06e2..58d9255b1 100644 --- a/src/runtime/BaseTypeAttributeBase.cs +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -6,7 +6,9 @@ namespace Python.Runtime /// Base class for all attributes, that override base type for C# classes as seen from Python /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum - | AttributeTargets.Interface | AttributeTargets.Struct)] + | AttributeTargets.Interface | AttributeTargets.Struct, + AllowMultiple = false, + Inherited = true)] public abstract class BaseTypeAttributeBase : Attribute { /// diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index dfce536b0..6abcef15a 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -234,17 +234,15 @@ static string CleanupFullName(string fullTypeName) return name; } - static IntPtr GetBaseType(Type clrType) { - var baseTypeOverride = clrType.GetCustomAttributes(inherit: false) - .OfType().SingleOrDefault(); - if (baseTypeOverride != null) + static IntPtr GetBaseType(Type clrType) + { + var baseOverride = GetLatestAttribute(clrType); + IntPtr handle = baseOverride?.BaseType(clrType) ?? IntPtr.Zero; + if (handle != IntPtr.Zero) { - IntPtr handle = baseTypeOverride.BaseType(clrType); - if (handle != IntPtr.Zero) - { - return handle; - } + return handle; } + if (clrType == typeof(Exception)) { return Exceptions.Exception; @@ -258,6 +256,38 @@ static IntPtr GetBaseType(Type clrType) { return IntPtr.Zero; } + /// + /// Walks the hierarchy of searching for the first + /// attribute of type from the down to . + /// + /// Type of the attribute to search for + /// The type potentially marked with the desired attribute + static T GetLatestAttribute(Type type) where T : Attribute + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + while (type != null) + { + var attribute = (T)type.GetCustomAttributes(attributeType: typeof(T), inherit: false).SingleOrDefault(); + if (attribute != null) + { + return attribute; + } + + if (type == typeof(object)) + { + return null; + } + + type = type.BaseType; + } + + return null; + } + internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) { // Utility to create a subtype of a managed type with the ability for the From 3b51d640baceacea5e8a2b2257f00d27669e17a6 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 28 Aug 2019 14:49:27 -0700 Subject: [PATCH 057/240] enable types to override their own conversion to Python --- src/embed_tests/TestCustomArgMarshal.cs | 29 +++++++++++++++++++++++++ src/runtime/IConvertibleToPython.cs | 17 +++++++++++++++ src/runtime/converter.cs | 18 ++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 src/runtime/IConvertibleToPython.cs diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 7c084d7f5..bc0333072 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -38,6 +38,28 @@ public void MarshallerOverride() { } Assert.AreEqual(expected: 42, actual: obj.LastArgument); } + + [Test] + public void ConvertibleToPython() { + var obj = new Convertible(convert: true); + int converted; + using (Py.GIL()) { + dynamic identity = PythonEngine.Eval("lambda o: o"); + converted = identity(obj); + } + Assert.AreEqual(expected: Convertible.Value, actual: converted); + } + + [Test] + public void ConvertibleToPythonBypass() { + var obj = new Convertible(convert: false); + Convertible converted; + using (Py.GIL()) { + dynamic identity = PythonEngine.Eval("lambda o: o"); + converted = identity(obj); + } + Assert.AreEqual(expected: obj, actual: converted); + } } [PyArgConverter(typeof(CustomArgConverter))] @@ -83,4 +105,11 @@ public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool n return true; } } + + class Convertible : IConvertibleToPython { + public const int Value = 42; + readonly bool convert; + public Convertible(bool convert) { this.convert = convert; } + public PyObject TryConvertToPython() => this.convert ? Value.ToPython() : null; + } } diff --git a/src/runtime/IConvertibleToPython.cs b/src/runtime/IConvertibleToPython.cs new file mode 100644 index 000000000..7d964fbf1 --- /dev/null +++ b/src/runtime/IConvertibleToPython.cs @@ -0,0 +1,17 @@ +namespace Python.Runtime +{ + /// + /// Implement this interface to change how instances + /// of your class are presented to Python interpreter. + /// + public interface IConvertibleToPython + { + /// + /// Converts current object to , + /// which can be passed to the Python interpreter. + /// + /// Returns null if conversion should be skipped + /// + PyObject TryConvertToPython(); + } +} diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 6d91ccfcd..e5d32ab4f 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -115,13 +115,25 @@ internal static IntPtr ToPython(T value) internal static IntPtr ToPython(object value, Type type) { - if (value is PyObject) + if (value is PyObject pyObject) { - IntPtr handle = ((PyObject)value).Handle; + IntPtr handle = pyObject.Handle; Runtime.XIncref(handle); return handle; } - IntPtr result = IntPtr.Zero; + + if (value is IConvertibleToPython convertible) + { + pyObject = convertible.TryConvertToPython(); + if (pyObject != null) + { + IntPtr handle = pyObject.Handle; + Runtime.XIncref(handle); + return handle; + } + } + + IntPtr result; // Null always converts to None in Python. From af9fce43b414923b7d72ef1f2f005d1f3c9b2bdf Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 30 Aug 2019 11:17:30 -0700 Subject: [PATCH 058/240] allow C# 7.3 in test code --- src/embed_tests/Python.EmbeddingTest.15.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index 8998e2794..682cfbe84 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -1,4 +1,4 @@ - + @@ -22,7 +22,7 @@ ..\..\ $(SolutionDir)\bin\ $(OutputPath)\$(TargetFramework)_publish - 6 + 7.3 prompt $(PYTHONNET_DEFINE_CONSTANTS) XPLAT From 43d4ff88dfc54024cd8ea9729523034db3dc0584 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 30 Aug 2019 11:28:58 -0700 Subject: [PATCH 059/240] enable custom Python -> C# marshaling for specific types A custom conversion mechanics can be defined by inheriting from ConvertibleFromPythonAttribute. That mechanic can later be applied to the necessary classes. --- src/embed_tests/TestCustomArgMarshal.cs | 40 ++++++++++++++ src/runtime/ConvertibleFromPythonAttribute.cs | 23 ++++++++ src/runtime/Util.cs | 35 +++++++++++- src/runtime/converter.cs | 53 +++++++++++++++++-- src/runtime/typemanager.cs | 34 +----------- 5 files changed, 146 insertions(+), 39 deletions(-) create mode 100644 src/runtime/ConvertibleFromPythonAttribute.cs diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index bc0333072..59deef0fb 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -4,6 +4,8 @@ namespace Python.EmbeddingTest { + using Runtime = Python.Runtime.Runtime; + class TestCustomArgMarshal { [OneTimeSetUp] @@ -60,6 +62,29 @@ public void ConvertibleToPythonBypass() { } Assert.AreEqual(expected: obj, actual: converted); } + + [Test] + public void ConvertibleFromPython() { + using (Py.GIL()) { + bool ok = false; + void Accept(ConvertibleFromPython obj) => ok = true; + dynamic callWithInt = PythonEngine.Eval("lambda f: f(42)"); + callWithInt(new Action(Accept)); + Assert.IsTrue(ok); + } + } + + [Test] + public void ConvertibleFromPythonBypass() { + using (Py.GIL()) { + bool ok = false; + void Accept(ConvertibleFromPython obj) => ok = true; + dynamic callWithInt = PythonEngine.Eval("lambda f: f('42')"); + Assert.Throws(() => + callWithInt(new Action(Accept)), + message: "Python.Runtime.PythonException : TypeError : No method matches given arguments: ()"); + } + } } [PyArgConverter(typeof(CustomArgConverter))] @@ -112,4 +137,19 @@ class Convertible : IConvertibleToPython { public Convertible(bool convert) { this.convert = convert; } public PyObject TryConvertToPython() => this.convert ? Value.ToPython() : null; } + + class ConvertibleAttribute : ConvertibleFromPythonAttribute { + public override bool TryConvertFromPython(IntPtr pyObj, out T value) { + if (Runtime.PyString_Check(pyObj)) { + value = default; + return false; + } + + value = Activator.CreateInstance(); + return true; + } + } + + [Convertible] + class ConvertibleFromPython { } } diff --git a/src/runtime/ConvertibleFromPythonAttribute.cs b/src/runtime/ConvertibleFromPythonAttribute.cs new file mode 100644 index 000000000..1190cf0e2 --- /dev/null +++ b/src/runtime/ConvertibleFromPythonAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace Python.Runtime +{ + /// + /// Base class for all attributes, that override converting Python values to specific types. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct + | AttributeTargets.Enum | AttributeTargets.Delegate, + AllowMultiple = false, + Inherited = true)] + public abstract class ConvertibleFromPythonAttribute: Attribute + { + /// + /// Converts Python object to type . + /// If conversion this converter does not support source or target type, it returns false instead. + /// + /// .NET type to convert Python object to + /// A pointer to Python object to convert + /// A variable, that will receive the converted object + public abstract bool TryConvertFromPython(IntPtr pyObj, out T value); + } +} diff --git a/src/runtime/Util.cs b/src/runtime/Util.cs index dc5f78608..b9f117bb4 100644 --- a/src/runtime/Util.cs +++ b/src/runtime/Util.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Runtime.InteropServices; namespace Python.Runtime @@ -29,5 +30,37 @@ internal static void WriteCLong(IntPtr type, int offset, Int64 flags) Marshal.WriteInt64(type, offset, flags); } } + + /// + /// Walks the hierarchy of searching for the first + /// attribute of type from the down to . + /// + /// Type of the attribute to search for + /// The type potentially marked with the desired attribute + internal static T GetLatestAttribute(Type type) where T : Attribute + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + + while (type != null) + { + var attribute = (T)type.GetCustomAttributes(attributeType: typeof(T), inherit: false).SingleOrDefault(); + if (attribute != null) + { + return attribute; + } + + if (type == typeof(object)) + { + return null; + } + + type = type.BaseType; + } + + return null; + } } -} \ No newline at end of file +} diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index e5d32ab4f..f9803bfb2 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Reflection; @@ -352,11 +353,6 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return ToArray(value, obType, out result, setError); } - if (obType.IsEnum) - { - return ToEnum(value, obType, out result, setError); - } - // Conversion to 'Object' is done based on some reasonable default // conversions (Python string -> managed string, Python int -> Int32 etc.). if (obType == objectType) @@ -443,9 +439,56 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return false; } + TypeCode typeCode = Type.GetTypeCode(obType); + if (typeCode == TypeCode.Object) + { + var converter = TypeConverterCache.GetOrAdd(obType, GetConverter); + + if (converter != null && converter(value, out result)) + { + return true; + } + } + + if (obType.IsEnum) + { + return ToEnum(value, obType, out result, setError); + } + return ToPrimitive(value, obType, out result, setError); } + static TryConvertFromPythonDelegate GetConverter(Type targetType) + { + var converterAttribute = Util.GetLatestAttribute(targetType); + if (converterAttribute == null) + { + return null; + } + + var convert = converterAttribute.GetType() + .GetMethod(nameof(converterAttribute.TryConvertFromPython), + BindingFlags.Instance | BindingFlags.Public); + if (convert == null) + { + throw new NotSupportedException($"The type {converterAttribute.GetType()} must have exactly one public conversion method"); + } + convert = convert.MakeGenericMethod(targetType); + + bool TryConvert(IntPtr pyObj, out object result) { + var @params = new object[] {pyObj, null}; + bool success = (bool)convert.Invoke(converterAttribute, @params); + result = @params[1]; + return success; + } + + return TryConvert; + } + + delegate bool TryConvertFromPythonDelegate(IntPtr pyObj, out object result); + static readonly ConcurrentDictionary TypeConverterCache = + new ConcurrentDictionary(); + /// /// Convert a Python value to an instance of a primitive managed type. /// diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 6abcef15a..395e2afd6 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -236,7 +236,7 @@ static string CleanupFullName(string fullTypeName) static IntPtr GetBaseType(Type clrType) { - var baseOverride = GetLatestAttribute(clrType); + var baseOverride = Util.GetLatestAttribute(clrType); IntPtr handle = baseOverride?.BaseType(clrType) ?? IntPtr.Zero; if (handle != IntPtr.Zero) { @@ -256,38 +256,6 @@ static IntPtr GetBaseType(Type clrType) return IntPtr.Zero; } - /// - /// Walks the hierarchy of searching for the first - /// attribute of type from the down to . - /// - /// Type of the attribute to search for - /// The type potentially marked with the desired attribute - static T GetLatestAttribute(Type type) where T : Attribute - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - while (type != null) - { - var attribute = (T)type.GetCustomAttributes(attributeType: typeof(T), inherit: false).SingleOrDefault(); - if (attribute != null) - { - return attribute; - } - - if (type == typeof(object)) - { - return null; - } - - type = type.BaseType; - } - - return null; - } - internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) { // Utility to create a subtype of a managed type with the ability for the From fd07c178f5083c71c40167b04f1fd77fc6b8cf89 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 30 Aug 2019 12:28:34 -0700 Subject: [PATCH 060/240] changed ConvertibleFromPythonAttribute to use PyObject instead of IntPtr, and pointers are an implementation detail --- src/embed_tests/TestCustomArgMarshal.cs | 4 ++-- src/runtime/ConvertibleFromPythonAttribute.cs | 6 +++--- src/runtime/converter.cs | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 59deef0fb..95f8713c4 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -139,8 +139,8 @@ class Convertible : IConvertibleToPython { } class ConvertibleAttribute : ConvertibleFromPythonAttribute { - public override bool TryConvertFromPython(IntPtr pyObj, out T value) { - if (Runtime.PyString_Check(pyObj)) { + public override bool TryConvertFromPython(PyObject pyObj, out T value) { + if (Runtime.PyString_Check(pyObj.Handle)) { value = default; return false; } diff --git a/src/runtime/ConvertibleFromPythonAttribute.cs b/src/runtime/ConvertibleFromPythonAttribute.cs index 1190cf0e2..342eb6495 100644 --- a/src/runtime/ConvertibleFromPythonAttribute.cs +++ b/src/runtime/ConvertibleFromPythonAttribute.cs @@ -16,8 +16,8 @@ public abstract class ConvertibleFromPythonAttribute: Attribute /// If conversion this converter does not support source or target type, it returns false instead. /// /// .NET type to convert Python object to - /// A pointer to Python object to convert - /// A variable, that will receive the converted object - public abstract bool TryConvertFromPython(IntPtr pyObj, out T value); + /// The Python object to convert + /// The variable, that will receive the converted object + public abstract bool TryConvertFromPython(PyObject pyObj, out T value); } } diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index f9803bfb2..48b999453 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -475,8 +475,9 @@ static TryConvertFromPythonDelegate GetConverter(Type targetType) } convert = convert.MakeGenericMethod(targetType); - bool TryConvert(IntPtr pyObj, out object result) { - var @params = new object[] {pyObj, null}; + bool TryConvert(IntPtr pyHandle, out object result) { + var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle)); + var @params = new object[] { pyObj, null }; bool success = (bool)convert.Invoke(converterAttribute, @params); result = @params[1]; return success; From 098d22fa2f0bba8389432835546210db2d86abb9 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 8 Sep 2019 12:28:31 -0700 Subject: [PATCH 061/240] minor change in Converter --- src/runtime/converter.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 48b999453..74c70c490 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -20,18 +20,18 @@ private Converter() { } - private static NumberFormatInfo nfi; - private static Type objectType; - private static Type stringType; - private static Type singleType; - private static Type doubleType; - private static Type decimalType; - private static Type int16Type; - private static Type int32Type; - private static Type int64Type; - private static Type flagsType; - private static Type boolType; - private static Type typeType; + private static readonly NumberFormatInfo nfi; + private static readonly Type objectType; + private static readonly Type stringType; + private static readonly Type singleType; + private static readonly Type doubleType; + private static readonly Type decimalType; + private static readonly Type int16Type; + private static readonly Type int32Type; + private static readonly Type int64Type; + private static readonly Type flagsType; + private static readonly Type boolType; + private static readonly Type typeType; static Converter() { From febe5a756ba4c0d8ebd2e7b31eb5bd323783f81c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 10 Sep 2019 11:33:20 -0700 Subject: [PATCH 062/240] added an ability to call base __getattr__ (ok) and __setattr__ (broken) __setattr__ does not work due to https://duckduckgo.com/?q="Py_TPFLAGS_HEAPTYPE"+"tp_setattro" See also: https://stackoverflow.com/questions/10161609/class-property-using-python-c-api https://mail.python.org/pipermail/python-dev/2008-February/077167.html https://stackoverflow.com/questions/57845816/how-to-call-base-class-setattr-and-getattr-properly-from-c --- src/embed_tests/Inheritance.cs | 8 ++- src/embed_tests/TestInstanceWrapping.cs | 49 ++++++++++++++ src/runtime/classobject.cs | 2 +- src/runtime/nativecall.cs | 13 ++++ src/runtime/slots.cs | 85 +++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index cd885fab7..07c373ad6 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -88,7 +88,13 @@ public class PythonWrapperBase { } [CustomBaseType] public class InheritanceTestBaseClassWrapper : PythonWrapperBase { public const string ClassName = "InheritanceTestBaseClass"; - public const string ClassSourceCode = "class " + ClassName + ": pass\n" + ClassName + " = " + ClassName + "\n"; + public const string ClassSourceCode = "class " + ClassName + +@": + def __getattr__(self, name): + return '__getattr__:' + name + def __setattr__(self, name, value): + value[name] = name +" + ClassName + " = " + ClassName + "\n"; } public class Inherited : InheritanceTestBaseClassWrapper { diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 2c2b0ebe0..dd2b765e3 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -9,6 +9,11 @@ public class TestInstanceWrapping { [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); + using (Py.GIL()) { + var locals = new PyDict(); + PythonEngine.Exec(InheritanceTestBaseClassWrapper.ClassSourceCode, locals: locals.Handle); + CustomBaseTypeAttribute.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + } } [OneTimeTearDown] @@ -96,6 +101,31 @@ public void SetAttrCanBeOverriden() { } } + [Test] + public void GetAttrCanCallBase() { + var obj = new GetSetAttrInherited(); + using (Py.GIL()) { + var pyObj = obj.ToPython(); + dynamic getNonexistingAttr = PythonEngine.Eval("lambda o: o.non_existing_attr"); + string nonexistentAttrValue = getNonexistingAttr(pyObj); + Assert.AreEqual("__getattr__:non_existing_attr", nonexistentAttrValue); + } + } + + [Test] + public void SetAttrCanCallBase() { + var obj = new GetSetAttrInherited(); + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + var pyObj = obj.ToPython(); + dynamic receiver = scope.Eval("dict()"); + scope.Set(nameof(pyObj), pyObj); + scope.Set(nameof(receiver), receiver); + scope.Exec($"{nameof(pyObj)}.non_existing_attr = {nameof(receiver)}"); + Assert.AreEqual("non_existing_attr", receiver["non_existing_attr"]); + } + } + const string GetAttrFallbackValue = "undefined"; class Base {} @@ -128,5 +158,24 @@ public bool TrySetAttr(string name, PyObject value) { return true; } } + + class GetSetAttrInherited : InheritanceTestBaseClassWrapper, IGetAttr, ISetAttr { + public bool TryGetAttr(string name, out PyObject value) { + if (name == "NonInherited") { + value = "NonInherited".ToPython(); + return true; + } + + return GetAttr.TryGetBaseAttr(this.ToPython(), CustomBaseTypeAttribute.BaseClass, name, out value); + } + + public bool TrySetAttr(string name, PyObject value) { + if (name == "NonInherited") return false; + + var self = this.ToPython(); + bool result = SetAttr.TrySetBaseAttr(self, name, value); + return result; + } + } } } diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 3fb7fd70a..a73daf177 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -356,7 +356,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) /// Get the first base class in the class hierarchy /// of the specified .NET type, that is defined in Python. /// - static IntPtr GetPythonBase(IntPtr tp) { + internal static IntPtr GetPythonBase(IntPtr tp) { Debug.Assert(IsManagedType(tp)); do { tp = Marshal.ReadIntPtr(tp, TypeOffset.tp_base); diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs index b5bf25dd7..df290ceb2 100644 --- a/src/runtime/nativecall.cs +++ b/src/runtime/nativecall.cs @@ -46,6 +46,12 @@ public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3) { return ((Int_3_Delegate)Marshal.GetDelegateForFunctionPointer(fp, typeof(Int_3_Delegate)))(a1, a2, a3); } + + public static IntPtr Call_2(IntPtr fp, IntPtr a1, IntPtr a2) + { + var d = (Interop.BinaryFunc)Marshal.GetDelegateForFunctionPointer(fp, typeof(Interop.BinaryFunc)); + return d(a1, a2); + } #else private static AssemblyBuilder aBuilder; private static ModuleBuilder mBuilder; @@ -147,6 +153,11 @@ public static void Void_Call_1(IntPtr fp, IntPtr a1) Impl.Void_Call_1(fp, a1); } + public static IntPtr Call_2(IntPtr fp, IntPtr a1, IntPtr a2) + { + return Impl.Call_2(fp, a1, a2); + } + public static IntPtr Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3) { return Impl.Call_3(fp, a1, a2, a3); @@ -169,6 +180,8 @@ public interface INativeCall void Void_Call_1(IntPtr funcPtr, IntPtr arg1); + IntPtr Call_2(IntPtr funcPtr, IntPtr a1, IntPtr a2); + int Int_Call_3(IntPtr funcPtr, IntPtr t, IntPtr n, IntPtr v); IntPtr Call_3(IntPtr funcPtr, IntPtr a1, IntPtr a2, IntPtr a3); diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index 85e35c299..07b789383 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; namespace Python.Runtime.Slots { @@ -44,4 +45,88 @@ public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { : Runtime.PyObject_GenericSetAttr(ob, key, val); } } + + public static class GetAttr { + static bool TryGetBaseAttr(PyObject self, IntPtr @base, string name, out PyObject result) { + if (self == null) throw new ArgumentNullException(nameof(self)); + if (@base == IntPtr.Zero) throw new ArgumentNullException(nameof(@base)); + if (name == null) throw new ArgumentNullException(nameof(name)); + + result = null; + + for (; @base != IntPtr.Zero; @base = Marshal.ReadIntPtr(@base, TypeOffset.tp_base)) { + IntPtr getAttr = Marshal.ReadIntPtr(@base, TypeOffset.tp_getattro); + if (getAttr == IntPtr.Zero) continue; + IntPtr resultPtr = NativeCall.Call_2(fp: getAttr, self.Handle, name.ToPython().Handle); + if (resultPtr != IntPtr.Zero) { + result = new PyObject(Runtime.SelfIncRef(resultPtr)); + return true; + } + + return false; + } + + return false; + } + + /// + /// Tries to call base type's __getattr__ on the specified instance. + /// Only use when base.TryGetAttr is not available. + /// + /// Python object to call __getattr__ on + /// Type in the object base type hierarchy, whose __getattr__ to call + /// Name of the attribute to retrieve + /// Reference to a variable, that will receive the attribute value + public static bool TryGetBaseAttr(PyObject self, PyObject baseType, string name, out PyObject result) { + if (baseType == null) throw new ArgumentNullException(nameof(baseType)); + + return TryGetBaseAttr(self, baseType.Handle, name, out result); + } + + /// + /// Tries to call base type's __getattr__ on the specified instance. + /// Only use when base.TryGetAttr is not available. + /// + /// Python object to call __getattr__ on + /// Name of the attribute to retrieve + /// Reference to a variable, that will receive the attribute value + public static bool TryGetBaseAttr(PyObject self, string name, out PyObject result) { + if (self == null) throw new ArgumentNullException(nameof(self)); + + IntPtr pythonType = Runtime.PyObject_TYPE(self.Handle); + IntPtr pythonBase = ClassObject.GetPythonBase(pythonType); + return TryGetBaseAttr(self, pythonBase, name, out result); + } + } + + public static class SetAttr { + public static bool TrySetBaseAttr(PyObject self, PyObject baseType, string name, PyObject value) { + if (baseType == null) throw new ArgumentNullException(nameof(baseType)); + return TrySetBaseAttr(self, baseType.Handle, name, value); + } + public static bool TrySetBaseAttr(PyObject self, string name, PyObject value) { + if (self == null) throw new ArgumentNullException(nameof(self)); + + IntPtr pythonType = Runtime.PyObject_TYPE(self.Handle); + IntPtr pythonBase = ClassObject.GetPythonBase(pythonType); + return TrySetBaseAttr(self, pythonBase, name, value); + } + + static bool TrySetBaseAttr(PyObject self, IntPtr @base, string name, PyObject value) { + if (self == null) throw new ArgumentNullException(nameof(self)); + if (name == null) throw new ArgumentNullException(nameof(name)); + + for (; @base != IntPtr.Zero; @base = Marshal.ReadIntPtr(@base, TypeOffset.tp_base)) { + IntPtr setAttr = Marshal.ReadIntPtr(@base, TypeOffset.tp_setattro); + if (setAttr == IntPtr.Zero) continue; + + int result = NativeCall.Int_Call_3(fp: setAttr, self.Handle, name.ToPython().Handle, + value?.Handle ?? IntPtr.Zero); + if (result != 0) throw PythonException.FromPyErr(); + return true; + } + + return false; + } + } } From 1d9c9554264077880f68c60941a849f49ea30b84 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 10 Sep 2019 11:49:18 -0700 Subject: [PATCH 063/240] check, that base Python type can be inherited from --- src/runtime/interop.cs | 3 +++ src/runtime/typemanager.cs | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index bb5b1de7e..ca3a3058b 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -264,6 +264,9 @@ public static void FreeModuleDef(IntPtr ptr) internal class TypeFlags { public static int HeapType = (1 << 9); + /// + /// Unless this flag is set, the type can't be inherited from (equivalent to C# sealed) + /// public static int BaseType = (1 << 10); public static int Ready = (1 << 12); public static int Readying = (1 << 13); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 395e2afd6..81332ad02 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -238,8 +238,11 @@ static IntPtr GetBaseType(Type clrType) { var baseOverride = Util.GetLatestAttribute(clrType); IntPtr handle = baseOverride?.BaseType(clrType) ?? IntPtr.Zero; - if (handle != IntPtr.Zero) - { + if (handle != IntPtr.Zero) { + if ((Util.ReadCLong(handle, TypeOffset.tp_flags) & TypeFlags.BaseType) == 0) { + throw new InvalidProgramException("The specified base Python type can not be inherited from"); + } + return handle; } From 93cb1cb8e9cd70f3cf49c342632fde5ec9bc63c4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 10 Sep 2019 13:07:55 -0700 Subject: [PATCH 064/240] invoke base.__getattr__ and base.__setattr__ via super() --- src/embed_tests/TestInstanceWrapping.cs | 8 ++- src/runtime/pyobject.cs | 31 ++++++++ src/runtime/runtime.cs | 2 + src/runtime/slots.cs | 95 +++++++++---------------- 4 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index dd2b765e3..cbcca570f 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -103,7 +103,7 @@ public void SetAttrCanBeOverriden() { [Test] public void GetAttrCanCallBase() { - var obj = new GetSetAttrInherited(); + var obj = new GetSetAttrDoubleInherited(); using (Py.GIL()) { var pyObj = obj.ToPython(); dynamic getNonexistingAttr = PythonEngine.Eval("lambda o: o.non_existing_attr"); @@ -114,7 +114,7 @@ public void GetAttrCanCallBase() { [Test] public void SetAttrCanCallBase() { - var obj = new GetSetAttrInherited(); + var obj = new GetSetAttrDoubleInherited(); using (Py.GIL()) using (var scope = Py.CreateScope()) { var pyObj = obj.ToPython(); @@ -166,7 +166,7 @@ public bool TryGetAttr(string name, out PyObject value) { return true; } - return GetAttr.TryGetBaseAttr(this.ToPython(), CustomBaseTypeAttribute.BaseClass, name, out value); + return GetAttr.TryGetBaseAttr(this.ToPython(), name, out value); } public bool TrySetAttr(string name, PyObject value) { @@ -177,5 +177,7 @@ public bool TrySetAttr(string name, PyObject value) { return result; } } + + class GetSetAttrDoubleInherited: GetSetAttrInherited { } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 59a9b2f56..ba58d362b 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -692,6 +692,37 @@ public PyObject InvokeMethod(string name, PyTuple args) return result; } + /// + /// InvokeMethod Method + /// + /// + /// Invoke the named method of the object with the given arguments. + /// A PythonException is raised if the invokation is unsuccessful. + /// + public PyObject InvokeMethod(PyObject name, params PyObject[] args) + { + PyObject method = GetAttr(name); + PyObject result = method.Invoke(args); + method.Dispose(); + return result; + } + + + /// + /// InvokeMethod Method + /// + /// + /// Invoke the named method of the object with the given arguments. + /// A PythonException is raised if the invokation is unsuccessful. + /// + public PyObject InvokeMethod(PyObject name, PyTuple args) + { + PyObject method = GetAttr(name); + PyObject result = method.Invoke(args); + method.Dispose(); + return result; + } + /// /// InvokeMethod Method diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 1394b15ec..2b8975099 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -349,6 +349,7 @@ internal static void Initialize(bool initSigs = false) PyNone = PyObject_GetAttrString(op, "None"); PyTrue = PyObject_GetAttrString(op, "True"); PyFalse = PyObject_GetAttrString(op, "False"); + PySuper = PyObject_GetAttrString(op, "super"); PyBoolType = PyObject_Type(PyTrue); PyNoneType = PyObject_Type(PyNone); @@ -547,6 +548,7 @@ internal static int AtExit() internal static IntPtr PyFalse; internal static IntPtr PyNone; internal static IntPtr Error; + internal static IntPtr PySuper; private static readonly Lazy inspect = new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index 07b789383..9a4c71a26 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -1,5 +1,5 @@ using System; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace Python.Runtime.Slots { @@ -28,6 +28,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (IGetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; string attr = Runtime.GetManagedString(key); + RuntimeHelpers.EnsureSufficientExecutionStack(); return self.TryGetAttr(attr, out var value) ? Runtime.SelfIncRef(value.Handle) : Runtime.PyObject_GenericGetAttr(ob, key); @@ -40,6 +41,7 @@ public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { var self = (ISetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; string attr = Runtime.GetManagedString(key); + RuntimeHelpers.EnsureSufficientExecutionStack(); return self.TrySetAttr(attr, new PyObject(Runtime.SelfIncRef(val))) ? 0 : Runtime.PyObject_GenericSetAttr(ob, key, val); @@ -47,41 +49,7 @@ public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { } public static class GetAttr { - static bool TryGetBaseAttr(PyObject self, IntPtr @base, string name, out PyObject result) { - if (self == null) throw new ArgumentNullException(nameof(self)); - if (@base == IntPtr.Zero) throw new ArgumentNullException(nameof(@base)); - if (name == null) throw new ArgumentNullException(nameof(name)); - - result = null; - - for (; @base != IntPtr.Zero; @base = Marshal.ReadIntPtr(@base, TypeOffset.tp_base)) { - IntPtr getAttr = Marshal.ReadIntPtr(@base, TypeOffset.tp_getattro); - if (getAttr == IntPtr.Zero) continue; - IntPtr resultPtr = NativeCall.Call_2(fp: getAttr, self.Handle, name.ToPython().Handle); - if (resultPtr != IntPtr.Zero) { - result = new PyObject(Runtime.SelfIncRef(resultPtr)); - return true; - } - - return false; - } - - return false; - } - - /// - /// Tries to call base type's __getattr__ on the specified instance. - /// Only use when base.TryGetAttr is not available. - /// - /// Python object to call __getattr__ on - /// Type in the object base type hierarchy, whose __getattr__ to call - /// Name of the attribute to retrieve - /// Reference to a variable, that will receive the attribute value - public static bool TryGetBaseAttr(PyObject self, PyObject baseType, string name, out PyObject result) { - if (baseType == null) throw new ArgumentNullException(nameof(baseType)); - - return TryGetBaseAttr(self, baseType.Handle, name, out result); - } + static readonly PyObject getAttr = "__getattr__".ToPython(); /// /// Tries to call base type's __getattr__ on the specified instance. @@ -92,41 +60,48 @@ public static bool TryGetBaseAttr(PyObject self, PyObject baseType, string name, /// Reference to a variable, that will receive the attribute value public static bool TryGetBaseAttr(PyObject self, string name, out PyObject result) { if (self == null) throw new ArgumentNullException(nameof(self)); + if (name == null) throw new ArgumentNullException(nameof(name)); - IntPtr pythonType = Runtime.PyObject_TYPE(self.Handle); - IntPtr pythonBase = ClassObject.GetPythonBase(pythonType); - return TryGetBaseAttr(self, pythonBase, name, out result); + using (var super = new PyObject(Runtime.PySuper)) + using (var @class = self.GetAttr("__class__")) + using (var @base = super.Invoke(@class, self)) { + if (!@base.HasAttr(getAttr)) { + result = null; + return false; + } + + using (var pythonName = name.ToPython()) { + result = @base.InvokeMethod(getAttr, pythonName); + return true; + } + } } } public static class SetAttr { - public static bool TrySetBaseAttr(PyObject self, PyObject baseType, string name, PyObject value) { - if (baseType == null) throw new ArgumentNullException(nameof(baseType)); - return TrySetBaseAttr(self, baseType.Handle, name, value); - } - public static bool TrySetBaseAttr(PyObject self, string name, PyObject value) { - if (self == null) throw new ArgumentNullException(nameof(self)); - - IntPtr pythonType = Runtime.PyObject_TYPE(self.Handle); - IntPtr pythonBase = ClassObject.GetPythonBase(pythonType); - return TrySetBaseAttr(self, pythonBase, name, value); - } + static readonly PyObject setAttr = "__setattr__".ToPython(); - static bool TrySetBaseAttr(PyObject self, IntPtr @base, string name, PyObject value) { + /// + /// Tries to call base type's __setattr__ on the specified instance. + /// Only use when base.TrySetAttr is not available. + /// + /// Python object to call __setattr__ on + /// Name of the attribute to write + /// New value for the attribute + public static bool TrySetBaseAttr(PyObject self, string name, PyObject value) { if (self == null) throw new ArgumentNullException(nameof(self)); if (name == null) throw new ArgumentNullException(nameof(name)); - for (; @base != IntPtr.Zero; @base = Marshal.ReadIntPtr(@base, TypeOffset.tp_base)) { - IntPtr setAttr = Marshal.ReadIntPtr(@base, TypeOffset.tp_setattro); - if (setAttr == IntPtr.Zero) continue; + using (var super = new PyObject(Runtime.PySuper)) + using (var @class = self.GetAttr("__class__")) + using (var @base = super.Invoke(@class, self)) { + if (!@base.HasAttr(setAttr)) return false; - int result = NativeCall.Int_Call_3(fp: setAttr, self.Handle, name.ToPython().Handle, - value?.Handle ?? IntPtr.Zero); - if (result != 0) throw PythonException.FromPyErr(); - return true; + using (var pythonName = name.ToPython()) { + @base.InvokeMethod(setAttr, pythonName, value)?.Dispose(); + return true; + } } - - return false; } } } From ad4ad7295a396d654c8e26fa92c7da8bf8446584 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 10 Sep 2019 13:11:20 -0700 Subject: [PATCH 065/240] removed ISetAttr, as it does not work properly with inheritance --- src/embed_tests/TestInstanceWrapping.cs | 43 ++-------------------- src/runtime/slots.cs | 47 ------------------------- src/runtime/typemanager.cs | 4 --- 3 files changed, 2 insertions(+), 92 deletions(-) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index cbcca570f..e5ac28dc1 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -89,18 +89,6 @@ public void GetAttrCanBeOverriden() { } } - [Test] - public void SetAttrCanBeOverriden() { - var overloaded = new Overloaded(); - using (Py.GIL()) - using (var scope = Py.CreateScope()) { - var o = overloaded.ToPython(); - scope.Set(nameof(o), o); - scope.Exec($"{nameof(o)}.non_existing_attr = 42"); - Assert.AreEqual(42, overloaded.Value); - } - } - [Test] public void GetAttrCanCallBase() { var obj = new GetSetAttrDoubleInherited(); @@ -112,26 +100,12 @@ public void GetAttrCanCallBase() { } } - [Test] - public void SetAttrCanCallBase() { - var obj = new GetSetAttrDoubleInherited(); - using (Py.GIL()) - using (var scope = Py.CreateScope()) { - var pyObj = obj.ToPython(); - dynamic receiver = scope.Eval("dict()"); - scope.Set(nameof(pyObj), pyObj); - scope.Set(nameof(receiver), receiver); - scope.Exec($"{nameof(pyObj)}.non_existing_attr = {nameof(receiver)}"); - Assert.AreEqual("non_existing_attr", receiver["non_existing_attr"]); - } - } - const string GetAttrFallbackValue = "undefined"; class Base {} class Derived: Base { } - class Overloaded: Derived, IGetAttr, ISetAttr + class Overloaded: Derived, IGetAttr { public int Value { get; set; } public void IntOrStr(int arg) => this.Value = arg; @@ -152,14 +126,9 @@ public bool TryGetAttr(string name, out PyObject value) { value = GetAttrFallbackValue.ToPython(); return true; } - - public bool TrySetAttr(string name, PyObject value) { - this.Value = value.As(); - return true; - } } - class GetSetAttrInherited : InheritanceTestBaseClassWrapper, IGetAttr, ISetAttr { + class GetSetAttrInherited : InheritanceTestBaseClassWrapper, IGetAttr { public bool TryGetAttr(string name, out PyObject value) { if (name == "NonInherited") { value = "NonInherited".ToPython(); @@ -168,14 +137,6 @@ public bool TryGetAttr(string name, out PyObject value) { return GetAttr.TryGetBaseAttr(this.ToPython(), name, out value); } - - public bool TrySetAttr(string name, PyObject value) { - if (name == "NonInherited") return false; - - var self = this.ToPython(); - bool result = SetAttr.TrySetBaseAttr(self, name, value); - return result; - } } class GetSetAttrDoubleInherited: GetSetAttrInherited { } diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index 9a4c71a26..d5d0f0a49 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -10,13 +10,6 @@ public interface IGetAttr { bool TryGetAttr(string name, out PyObject value); } - /// - /// Implement this interface to override Python's __setattr__ for your class - /// - public interface ISetAttr { - bool TrySetAttr(string name, PyObject value); - } - static class SlotOverrides { public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { IntPtr genericResult = Runtime.PyObject_GenericGetAttr(ob, key); @@ -33,19 +26,6 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { ? Runtime.SelfIncRef(value.Handle) : Runtime.PyObject_GenericGetAttr(ob, key); } - - public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) { - if (!Runtime.PyString_Check(key)) { - return Runtime.PyObject_GenericSetAttr(ob, key, val); - } - - var self = (ISetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; - string attr = Runtime.GetManagedString(key); - RuntimeHelpers.EnsureSufficientExecutionStack(); - return self.TrySetAttr(attr, new PyObject(Runtime.SelfIncRef(val))) - ? 0 - : Runtime.PyObject_GenericSetAttr(ob, key, val); - } } public static class GetAttr { @@ -77,31 +57,4 @@ public static bool TryGetBaseAttr(PyObject self, string name, out PyObject resul } } } - - public static class SetAttr { - static readonly PyObject setAttr = "__setattr__".ToPython(); - - /// - /// Tries to call base type's __setattr__ on the specified instance. - /// Only use when base.TrySetAttr is not available. - /// - /// Python object to call __setattr__ on - /// Name of the attribute to write - /// New value for the attribute - public static bool TrySetBaseAttr(PyObject self, string name, PyObject value) { - if (self == null) throw new ArgumentNullException(nameof(self)); - if (name == null) throw new ArgumentNullException(nameof(name)); - - using (var super = new PyObject(Runtime.PySuper)) - using (var @class = self.GetAttr("__class__")) - using (var @base = super.Invoke(@class, self)) { - if (!@base.HasAttr(setAttr)) return false; - - using (var pythonName = name.ToPython()) { - @base.InvokeMethod(setAttr, pythonName, value)?.Dispose(); - return true; - } - } - } - } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 81332ad02..c8e0df7c0 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -136,10 +136,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); } - if (typeof(ISetAttr).IsAssignableFrom(clrType)) { - InitializeSlot(type, TypeOffset.tp_setattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_setattro))); - } - IntPtr base_ = GetBaseType(clrType); if (base_ != IntPtr.Zero) { From 12c5539c0dbe53be7fd255191f33029b6d789026 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 11:57:32 -0700 Subject: [PATCH 066/240] don't try to call generic getattr before calling user-supplied override --- src/embed_tests/TestInstanceWrapping.cs | 6 ++++++ src/runtime/slots.cs | 26 ++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index e5ac28dc1..6552c8660 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -123,6 +123,12 @@ public void IntOrStr(string arg) => public void BaseOrDerived(Derived _) => this.Value = Derived; public bool TryGetAttr(string name, out PyObject value) { + using (var self = this.ToPython()) { + if (GetAttr.TryGetBaseAttr(self, name, out value) + || GetAttr.GenericGetAttr(self, name, out value)) + return true; + } + value = GetAttrFallbackValue.ToPython(); return true; } diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index d5d0f0a49..db4c7e748 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -12,8 +12,8 @@ public interface IGetAttr { static class SlotOverrides { public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { - IntPtr genericResult = Runtime.PyObject_GenericGetAttr(ob, key); - if (genericResult != IntPtr.Zero || !Runtime.PyString_Check(key)) { + if (!Runtime.PyString_Check(key)) { + IntPtr genericResult = Runtime.PyObject_GenericGetAttr(ob, key); return genericResult; } @@ -43,7 +43,7 @@ public static bool TryGetBaseAttr(PyObject self, string name, out PyObject resul if (name == null) throw new ArgumentNullException(nameof(name)); using (var super = new PyObject(Runtime.PySuper)) - using (var @class = self.GetAttr("__class__")) + using (var @class = self.GetPythonType()) using (var @base = super.Invoke(@class, self)) { if (!@base.HasAttr(getAttr)) { result = null; @@ -56,5 +56,25 @@ public static bool TryGetBaseAttr(PyObject self, string name, out PyObject resul } } } + + public static bool GenericGetAttr(PyObject self, string name, out PyObject result) { + if (self == null) throw new ArgumentNullException(nameof(self)); + if (name == null) throw new ArgumentNullException(nameof(name)); + + using (var pyName = name.ToPython()) { + IntPtr pyResult = Runtime.PyObject_GenericGetAttr(self.Handle, pyName.Handle); + if (pyResult == IntPtr.Zero) { + result = null; + if (!PythonException.Matches(Exceptions.AttributeError)) { + throw PythonException.FromPyErr(); + } + + Exceptions.Clear(); + return false; + } + result = new PyObject(Runtime.SelfIncRef(pyResult)); + return true; + } + } } } From 9768c756a77174f3022c2fc8941b336e6b3b5789 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 11:58:20 -0700 Subject: [PATCH 067/240] fixed a number of warnings, added some news ones instead --- pythonnet.15.sln | 10 + src/runtime/Util.cs | 2 +- src/runtime/assemblymanager.cs | 11 +- src/runtime/classderived.cs | 2 +- src/runtime/debughelper.cs | 2 +- src/runtime/delegatemanager.cs | 11 +- src/runtime/interop.cs | 4 +- src/runtime/interop34.cs | 2 +- src/runtime/interop35.cs | 2 +- src/runtime/interop36.cs | 2 +- src/runtime/interop37.cs | 2 +- src/runtime/methodbinder.cs | 1 + src/runtime/nativecall.cs | 2 +- src/runtime/runtime.cs | 459 +++++++++++++++++---------------- src/runtime/slots.cs | 3 +- src/runtime/typemanager.cs | 2 +- tools/geninterop/geninterop.py | 2 +- 17 files changed, 265 insertions(+), 254 deletions(-) diff --git a/pythonnet.15.sln b/pythonnet.15.sln index 48b7ba717..114b1cdf4 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -18,6 +18,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{B6E8FE48-C global.json = global.json EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{A778EAEA-4A18-4EC1-BBBA-C0992E785F4E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "geninterop", "geninterop", "{18611402-C364-4564-9954-5F02DA8D1497}" + ProjectSection(SolutionItems) = preProject + tools\geninterop\geninterop.py = tools\geninterop\geninterop.py + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -48,6 +55,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {18611402-C364-4564-9954-5F02DA8D1497} = {A778EAEA-4A18-4EC1-BBBA-C0992E785F4E} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A6347B90-BBE6-4E45-90BF-1BD8B76069E3} EndGlobalSection diff --git a/src/runtime/Util.cs b/src/runtime/Util.cs index b9f117bb4..bb436b5cd 100644 --- a/src/runtime/Util.cs +++ b/src/runtime/Util.cs @@ -4,7 +4,7 @@ namespace Python.Runtime { - internal class Util + internal static class Util { internal static Int64 ReadCLong(IntPtr tp, int offset) { diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index 3085bb639..244ee720f 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -204,8 +204,9 @@ public static Assembly LoadAssembly(string name) { assembly = Assembly.Load(name); } - catch (Exception) + catch (Exception e) { + Trace.WriteLine($"{nameof(AssemblyManager)} failed to load assembly {name}: {e}"); //if (!(e is System.IO.FileNotFoundException)) //{ // throw; @@ -228,8 +229,9 @@ public static Assembly LoadAssemblyPath(string name) { assembly = Assembly.LoadFrom(path); } - catch (Exception) + catch (Exception e) { + Trace.WriteLine($"{nameof(AssemblyManager)} failed to load assembly {name}: {e}"); } } return assembly; @@ -255,8 +257,9 @@ public static Assembly LoadAssemblyFullPath(string name) { assembly = Assembly.LoadFrom(name); } - catch (Exception) + catch (Exception e) { + Trace.WriteLine($"{nameof(AssemblyManager)} failed to load assembly {name}: {e}"); } } } @@ -492,4 +495,4 @@ internal static Type[] GetTypes(Assembly a) } } } -} \ No newline at end of file +} diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index ec3734ea5..e56e25a62 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -621,7 +621,7 @@ private static ModuleBuilder GetModuleBuilder(string assemblyName, string module /// This has to be public as it's called from methods on dynamically built classes /// potentially in other assemblies. /// - public class PythonDerivedType + public static class PythonDerivedType { /// /// This is the implementation of the overridden methods in the derived diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index 3fe9ee5bb..287a140a8 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -11,7 +11,7 @@ namespace Python.Runtime /// The methods are only executed when the DEBUG flag is set. Otherwise /// they are automagically hidden by the compiler and silently suppressed. /// - internal class DebugUtil + internal static class DebugUtil { [Conditional("DEBUG")] public static void Print(string msg, params IntPtr[] args) diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 88a83ca28..080aa6c84 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -212,20 +212,15 @@ public Dispatcher(IntPtr target, Type dtype) public object Dispatch(ArrayList args) { IntPtr gs = PythonEngine.AcquireLock(); - object ob = null; try { - ob = TrueDispatch(args); + return TrueDispatch(args); } - catch (Exception e) + finally { PythonEngine.ReleaseLock(gs); - throw e; } - - PythonEngine.ReleaseLock(gs); - return ob; } public object TrueDispatch(ArrayList args) @@ -279,5 +274,7 @@ public ConversionException() public ConversionException(string msg) : base(msg) { } + + public ConversionException(string message, Exception innerException):base(message, innerException) { } } } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index ca3a3058b..882315913 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -69,7 +69,7 @@ public ModulePropertyAttribute() [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class ObjectOffset + internal static class ObjectOffset { static ObjectOffset() { @@ -261,7 +261,7 @@ public static void FreeModuleDef(IntPtr ptr) /// Note that the two values reserved for stackless have been put /// to good use as PythonNet specific flags (Managed and Subclass) /// - internal class TypeFlags + internal static class TypeFlags { public static int HeapType = (1 << 9); /// diff --git a/src/runtime/interop34.cs b/src/runtime/interop34.cs index 2723aacdc..c4bff98a7 100644 --- a/src/runtime/interop34.cs +++ b/src/runtime/interop34.cs @@ -11,7 +11,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset34 + internal static class TypeOffset34 { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; diff --git a/src/runtime/interop35.cs b/src/runtime/interop35.cs index a95fbed9a..9411432f0 100644 --- a/src/runtime/interop35.cs +++ b/src/runtime/interop35.cs @@ -11,7 +11,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset35 + internal static class TypeOffset35 { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs index 058be9639..540f11ed0 100644 --- a/src/runtime/interop36.cs +++ b/src/runtime/interop36.cs @@ -11,7 +11,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset36 + internal static class TypeOffset36 { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; diff --git a/src/runtime/interop37.cs b/src/runtime/interop37.cs index c817f7a9b..b98a45b06 100644 --- a/src/runtime/interop37.cs +++ b/src/runtime/interop37.cs @@ -11,7 +11,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset37 + internal static class TypeOffset37 { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index b94be3f40..2c2f71763 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -404,6 +404,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth /// /// Information about expected parameters /// true, if the last parameter is a params array. + /// Converter, that will be used to convert marshal arguments to .NET /// A pointer to the Python argument tuple /// Number of arguments, passed by Python /// A list of default values for omitted parameters diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs index df290ceb2..63692716e 100644 --- a/src/runtime/nativecall.cs +++ b/src/runtime/nativecall.cs @@ -21,7 +21,7 @@ namespace Python.Runtime /// build process to generate the thunks as a separate assembly /// that could then be referenced by the main Python runtime. /// - internal class NativeCall + internal static class NativeCall { #if NETSTANDARD [UnmanagedFunctionPointer(CallingConvention.Cdecl)] diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 2b8975099..08bce609f 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -67,7 +67,7 @@ public static IntPtr UnixGetProcAddress(IntPtr dllHandle, string name) return res; } - class Linux + static class Linux { [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr dlopen(String fileName, int flags); @@ -82,7 +82,7 @@ class Linux internal static extern IntPtr dlerror(); } - class Mac + static class Mac { [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr dlopen(String fileName, int flags); @@ -150,7 +150,7 @@ internal static T Throw(Exception exception) /// the responsibility of the caller to have acquired the GIL /// before calling any of these methods. /// - public class Runtime + public static class Runtime { static Runtime() { lock (VerLock) { @@ -1095,6 +1095,7 @@ internal static IntPtr PyInt_FromInt64(long value) return PyInt_FromLong(v); } + [Obsolete("Should not be used due to the size of long not being guaranteed")] private static IntPtr PyInt_FromLong(IntPtr value) => Delegates.PyInt_FromLong(value); internal static int PyInt_AsLong(IntPtr value) => Delegates.PyInt_AsLong(value); @@ -1107,34 +1108,34 @@ internal static bool PyLong_Check(IntPtr ob) return PyObject_TYPE(ob) == PyLongType; } - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static IntPtr PyLong_FromLong(long value) => Delegates.PyLong_FromLong(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static IntPtr PyLong_FromUnsignedLong(uint value) => Delegates.PyLong_FromUnsignedLong(value); internal static IntPtr PyLong_FromDouble(double value) => Delegates.PyLong_FromDouble(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static IntPtr PyLong_FromLongLong(long value) => Delegates.PyLong_FromLongLong(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static IntPtr PyLong_FromUnsignedLongLong(ulong value) => Delegates.PyLong_FromUnsignedLongLong(value); internal static IntPtr PyLong_FromString(string value, IntPtr end, int radix) => Delegates.PyLong_FromString(value, end, radix); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static int PyLong_AsLong(IntPtr value) => Delegates.PyLong_AsLong(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static uint PyLong_AsUnsignedLong(IntPtr value) => Delegates.PyLong_AsUnsignedLong(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static long PyLong_AsLongLong(IntPtr value) => Delegates.PyLong_AsLongLong(value); - + [Obsolete("Should not be used due to the size of long not being guaranteed")] internal static ulong PyLong_AsUnsignedLongLong(IntPtr value) => Delegates.PyLong_AsUnsignedLongLong(value); internal static bool PyFloat_Check(IntPtr ob) @@ -2048,92 +2049,92 @@ static T GetDelegateForFunctionPointer(IntPtr functionPointer) { internal static Py_IncRefDelegate Py_IncRef { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_IncRefDelegate(IntPtr ob); + internal delegate void Py_IncRefDelegate(IntPtr ob); internal static Py_DecRefDelegate Py_DecRef { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_DecRefDelegate(IntPtr ob); + internal delegate void Py_DecRefDelegate(IntPtr ob); internal static Py_InitializeDelegate Py_Initialize { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_InitializeDelegate(); + internal delegate void Py_InitializeDelegate(); internal static Py_InitializeExDelegate Py_InitializeEx { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_InitializeExDelegate(int initsigs); + internal delegate void Py_InitializeExDelegate(int initsigs); internal static Py_IsInitializedDelegate Py_IsInitialized { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int Py_IsInitializedDelegate(); + internal delegate int Py_IsInitializedDelegate(); internal static Py_FinalizeDelegate Py_Finalize { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_FinalizeDelegate(); + internal delegate void Py_FinalizeDelegate(); internal static Py_NewInterpreterDelegate Py_NewInterpreter { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_NewInterpreterDelegate(); + internal delegate IntPtr Py_NewInterpreterDelegate(); internal static Py_EndInterpreterDelegate Py_EndInterpreter { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_EndInterpreterDelegate(IntPtr threadState); + internal delegate void Py_EndInterpreterDelegate(IntPtr threadState); internal static PyThreadState_NewDelegate PyThreadState_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyThreadState_NewDelegate(IntPtr istate); + internal delegate IntPtr PyThreadState_NewDelegate(IntPtr istate); internal static PyThreadState_GetDelegate PyThreadState_Get { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyThreadState_GetDelegate(); + internal delegate IntPtr PyThreadState_GetDelegate(); internal static PyThread_get_key_valueDelegate PyThread_get_key_value { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyThread_get_key_valueDelegate(IntPtr key); + internal delegate IntPtr PyThread_get_key_valueDelegate(IntPtr key); internal static PyThread_get_thread_identDelegate PyThread_get_thread_ident { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyThread_get_thread_identDelegate(); + internal delegate int PyThread_get_thread_identDelegate(); internal static PyThread_set_key_valueDelegate PyThread_set_key_value { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyThread_set_key_valueDelegate(IntPtr key, IntPtr value); + internal delegate int PyThread_set_key_valueDelegate(IntPtr key, IntPtr value); internal static PyThreadState_SwapDelegate PyThreadState_Swap { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyThreadState_SwapDelegate(IntPtr key); + internal delegate IntPtr PyThreadState_SwapDelegate(IntPtr key); internal static PyGILState_EnsureDelegate PyGILState_Ensure { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyGILState_EnsureDelegate(); + internal delegate IntPtr PyGILState_EnsureDelegate(); internal static PyGILState_ReleaseDelegate PyGILState_Release { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyGILState_ReleaseDelegate(IntPtr gs); + internal delegate void PyGILState_ReleaseDelegate(IntPtr gs); internal static PyGILState_GetThisThreadStateDelegate PyGILState_GetThisThreadState { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyGILState_GetThisThreadStateDelegate(); + internal delegate IntPtr PyGILState_GetThisThreadStateDelegate(); internal static Py_MainDelegate Py_Main { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int Py_MainDelegate( + internal delegate int Py_MainDelegate( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv ); @@ -2141,582 +2142,582 @@ public delegate int Py_MainDelegate( internal static PyEval_InitThreadsDelegate PyEval_InitThreads { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_InitThreadsDelegate(); + internal delegate void PyEval_InitThreadsDelegate(); internal static PyEval_ThreadsInitializedDelegate PyEval_ThreadsInitialized { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyEval_ThreadsInitializedDelegate(); + internal delegate int PyEval_ThreadsInitializedDelegate(); internal static PyEval_AcquireLockDelegate PyEval_AcquireLock { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_AcquireLockDelegate(); + internal delegate void PyEval_AcquireLockDelegate(); internal static PyEval_ReleaseLockDelegate PyEval_ReleaseLock { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_ReleaseLockDelegate(); + internal delegate void PyEval_ReleaseLockDelegate(); internal static PyEval_AcquireThreadDelegate PyEval_AcquireThread { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_AcquireThreadDelegate(IntPtr tstate); + internal delegate void PyEval_AcquireThreadDelegate(IntPtr tstate); internal static PyEval_ReleaseThreadDelegate PyEval_ReleaseThread { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_ReleaseThreadDelegate(IntPtr tstate); + internal delegate void PyEval_ReleaseThreadDelegate(IntPtr tstate); internal static PyEval_SaveThreadDelegate PyEval_SaveThread { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyEval_SaveThreadDelegate(); + internal delegate IntPtr PyEval_SaveThreadDelegate(); internal static PyEval_RestoreThreadDelegate PyEval_RestoreThread { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyEval_RestoreThreadDelegate(IntPtr tstate); + internal delegate void PyEval_RestoreThreadDelegate(IntPtr tstate); internal static PyEval_GetBuiltinsDelegate PyEval_GetBuiltins { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyEval_GetBuiltinsDelegate(); + internal delegate IntPtr PyEval_GetBuiltinsDelegate(); internal static PyEval_GetGlobalsDelegate PyEval_GetGlobals { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyEval_GetGlobalsDelegate(); + internal delegate IntPtr PyEval_GetGlobalsDelegate(); internal static PyEval_GetLocalsDelegate PyEval_GetLocals { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyEval_GetLocalsDelegate(); + internal delegate IntPtr PyEval_GetLocalsDelegate(); internal static Py_GetProgramNameDelegate Py_GetProgramName { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetProgramNameDelegate(); + internal delegate IntPtr Py_GetProgramNameDelegate(); internal static Py_SetProgramNameDelegate Py_SetProgramName { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_SetProgramNameDelegate(IntPtr name); + internal delegate void Py_SetProgramNameDelegate(IntPtr name); internal static Py_GetPythonHomeDelegate Py_GetPythonHome { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetPythonHomeDelegate(); + internal delegate IntPtr Py_GetPythonHomeDelegate(); internal static Py_SetPythonHomeDelegate Py_SetPythonHome { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_SetPythonHomeDelegate(IntPtr home); + internal delegate void Py_SetPythonHomeDelegate(IntPtr home); internal static Py_GetPathDelegate Py_GetPath { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetPathDelegate(); + internal delegate IntPtr Py_GetPathDelegate(); internal static Py_SetPathDelegate Py_SetPath { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void Py_SetPathDelegate(IntPtr home); + internal delegate void Py_SetPathDelegate(IntPtr home); internal static Py_GetVersionDelegate Py_GetVersion { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetVersionDelegate(); + internal delegate IntPtr Py_GetVersionDelegate(); internal static Py_GetPlatformDelegate Py_GetPlatform { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetPlatformDelegate(); + internal delegate IntPtr Py_GetPlatformDelegate(); internal static Py_GetCopyrightDelegate Py_GetCopyright { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetCopyrightDelegate(); + internal delegate IntPtr Py_GetCopyrightDelegate(); internal static Py_GetCompilerDelegate Py_GetCompiler { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetCompilerDelegate(); + internal delegate IntPtr Py_GetCompilerDelegate(); internal static Py_GetBuildInfoDelegate Py_GetBuildInfo { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_GetBuildInfoDelegate(); + internal delegate IntPtr Py_GetBuildInfoDelegate(); internal static PyRun_SimpleStringDelegate PyRun_SimpleString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyRun_SimpleStringDelegate(string code); + internal delegate int PyRun_SimpleStringDelegate(string code); internal static PyRun_StringDelegate PyRun_String { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyRun_StringDelegate(string code, IntPtr st, IntPtr globals, IntPtr locals); + internal delegate IntPtr PyRun_StringDelegate(string code, IntPtr st, IntPtr globals, IntPtr locals); internal static PyEval_EvalCodeDelegate PyEval_EvalCode { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyEval_EvalCodeDelegate(IntPtr co, IntPtr globals, IntPtr locals); + internal delegate IntPtr PyEval_EvalCodeDelegate(IntPtr co, IntPtr globals, IntPtr locals); internal static Py_CompileStringDelegate Py_CompileString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr Py_CompileStringDelegate(string code, string file, IntPtr tok); + internal delegate IntPtr Py_CompileStringDelegate(string code, string file, IntPtr tok); internal static PyImport_ExecCodeModuleDelegate PyImport_ExecCodeModule { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_ExecCodeModuleDelegate(string name, IntPtr code); + internal delegate IntPtr PyImport_ExecCodeModuleDelegate(string name, IntPtr code); internal static PyCFunction_NewExDelegate PyCFunction_NewEx { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyCFunction_NewExDelegate(IntPtr ml, IntPtr self, IntPtr mod); + internal delegate IntPtr PyCFunction_NewExDelegate(IntPtr ml, IntPtr self, IntPtr mod); internal static PyCFunction_CallDelegate PyCFunction_Call { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyCFunction_CallDelegate(IntPtr func, IntPtr args, IntPtr kw); + internal delegate IntPtr PyCFunction_CallDelegate(IntPtr func, IntPtr args, IntPtr kw); internal static PyObject_HasAttrStringDelegate PyObject_HasAttrString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_HasAttrStringDelegate(IntPtr pointer, string name); + internal delegate int PyObject_HasAttrStringDelegate(IntPtr pointer, string name); internal static PyObject_GetAttrStringDelegate PyObject_GetAttrString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GetAttrStringDelegate(IntPtr pointer, string name); + internal delegate IntPtr PyObject_GetAttrStringDelegate(IntPtr pointer, string name); internal static PyObject_SetAttrStringDelegate PyObject_SetAttrString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_SetAttrStringDelegate(IntPtr pointer, string name, IntPtr value); + internal delegate int PyObject_SetAttrStringDelegate(IntPtr pointer, string name, IntPtr value); internal static PyObject_HasAttrDelegate PyObject_HasAttr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_HasAttrDelegate(IntPtr pointer, IntPtr name); + internal delegate int PyObject_HasAttrDelegate(IntPtr pointer, IntPtr name); internal static PyObject_GetAttrDelegate PyObject_GetAttr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GetAttrDelegate(IntPtr pointer, IntPtr name); + internal delegate IntPtr PyObject_GetAttrDelegate(IntPtr pointer, IntPtr name); internal static PyObject_SetAttrDelegate PyObject_SetAttr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_SetAttrDelegate(IntPtr pointer, IntPtr name, IntPtr value); + internal delegate int PyObject_SetAttrDelegate(IntPtr pointer, IntPtr name, IntPtr value); internal static PyObject_GetItemDelegate PyObject_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GetItemDelegate(IntPtr pointer, IntPtr key); + internal delegate IntPtr PyObject_GetItemDelegate(IntPtr pointer, IntPtr key); internal static PyObject_SetItemDelegate PyObject_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); + internal delegate int PyObject_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); internal static PyObject_DelItemDelegate PyObject_DelItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_DelItemDelegate(IntPtr pointer, IntPtr key); + internal delegate int PyObject_DelItemDelegate(IntPtr pointer, IntPtr key); internal static PyObject_GetIterDelegate PyObject_GetIter { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GetIterDelegate(IntPtr op); + internal delegate IntPtr PyObject_GetIterDelegate(IntPtr op); internal static PyObject_CallDelegate PyObject_Call { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_CallDelegate(IntPtr pointer, IntPtr args, IntPtr kw); + internal delegate IntPtr PyObject_CallDelegate(IntPtr pointer, IntPtr args, IntPtr kw); internal static PyObject_CallObjectDelegate PyObject_CallObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_CallObjectDelegate(IntPtr pointer, IntPtr args); + internal delegate IntPtr PyObject_CallObjectDelegate(IntPtr pointer, IntPtr args); internal static PyObject_RichCompareBoolDelegate PyObject_RichCompareBool { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_RichCompareBoolDelegate(IntPtr value1, IntPtr value2, int opid); + internal delegate int PyObject_RichCompareBoolDelegate(IntPtr value1, IntPtr value2, int opid); internal static PyObject_IsInstanceDelegate PyObject_IsInstance { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_IsInstanceDelegate(IntPtr ob, IntPtr type); + internal delegate int PyObject_IsInstanceDelegate(IntPtr ob, IntPtr type); internal static PyObject_IsSubclassDelegate PyObject_IsSubclass { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_IsSubclassDelegate(IntPtr ob, IntPtr type); + internal delegate int PyObject_IsSubclassDelegate(IntPtr ob, IntPtr type); internal static PyCallable_CheckDelegate PyCallable_Check { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyCallable_CheckDelegate(IntPtr pointer); + internal delegate int PyCallable_CheckDelegate(IntPtr pointer); internal static PyObject_IsTrueDelegate PyObject_IsTrue { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_IsTrueDelegate(IntPtr pointer); + internal delegate int PyObject_IsTrueDelegate(IntPtr pointer); internal static PyObject_NotDelegate PyObject_Not { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_NotDelegate(IntPtr pointer); + internal delegate int PyObject_NotDelegate(IntPtr pointer); internal static _PyObject_SizeDelegate _PyObject_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyObject_SizeDelegate(IntPtr pointer); + internal delegate IntPtr _PyObject_SizeDelegate(IntPtr pointer); internal static PyObject_HashDelegate PyObject_Hash { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_HashDelegate(IntPtr op); + internal delegate IntPtr PyObject_HashDelegate(IntPtr op); internal static PyObject_ReprDelegate PyObject_Repr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_ReprDelegate(IntPtr pointer); + internal delegate IntPtr PyObject_ReprDelegate(IntPtr pointer); internal static PyObject_StrDelegate PyObject_Str { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_StrDelegate(IntPtr pointer); + internal delegate IntPtr PyObject_StrDelegate(IntPtr pointer); internal static PyObject_UnicodeDelegate PyObject_Unicode { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_UnicodeDelegate(IntPtr pointer); + internal delegate IntPtr PyObject_UnicodeDelegate(IntPtr pointer); internal static PyObject_DirDelegate PyObject_Dir { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_DirDelegate(IntPtr pointer); + internal delegate IntPtr PyObject_DirDelegate(IntPtr pointer); internal static PyNumber_IntDelegate PyNumber_Int { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_IntDelegate(IntPtr ob); + internal delegate IntPtr PyNumber_IntDelegate(IntPtr ob); internal static PyNumber_LongDelegate PyNumber_Long { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_LongDelegate(IntPtr ob); + internal delegate IntPtr PyNumber_LongDelegate(IntPtr ob); internal static PyNumber_FloatDelegate PyNumber_Float { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_FloatDelegate(IntPtr ob); + internal delegate IntPtr PyNumber_FloatDelegate(IntPtr ob); internal static PyNumber_CheckDelegate PyNumber_Check { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate bool PyNumber_CheckDelegate(IntPtr ob); + internal delegate bool PyNumber_CheckDelegate(IntPtr ob); internal static PyInt_FromLongDelegate PyInt_FromLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyInt_FromLongDelegate(IntPtr value); + internal delegate IntPtr PyInt_FromLongDelegate(IntPtr value); internal static PyInt_AsLongDelegate PyInt_AsLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyInt_AsLongDelegate(IntPtr value); + internal delegate int PyInt_AsLongDelegate(IntPtr value); internal static PyInt_FromStringDelegate PyInt_FromString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyInt_FromStringDelegate(string value, IntPtr end, int radix); + internal delegate IntPtr PyInt_FromStringDelegate(string value, IntPtr end, int radix); internal static PyLong_FromLongDelegate PyLong_FromLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromLongDelegate(long value); + internal delegate IntPtr PyLong_FromLongDelegate(long value); internal static PyLong_FromUnsignedLongDelegate PyLong_FromUnsignedLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromUnsignedLongDelegate(uint value); + internal delegate IntPtr PyLong_FromUnsignedLongDelegate(uint value); internal static PyLong_FromDoubleDelegate PyLong_FromDouble { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromDoubleDelegate(double value); + internal delegate IntPtr PyLong_FromDoubleDelegate(double value); internal static PyLong_FromLongLongDelegate PyLong_FromLongLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromLongLongDelegate(long value); + internal delegate IntPtr PyLong_FromLongLongDelegate(long value); internal static PyLong_FromUnsignedLongLongDelegate PyLong_FromUnsignedLongLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromUnsignedLongLongDelegate(ulong value); + internal delegate IntPtr PyLong_FromUnsignedLongLongDelegate(ulong value); internal static PyLong_FromStringDelegate PyLong_FromString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyLong_FromStringDelegate(string value, IntPtr end, int radix); + internal delegate IntPtr PyLong_FromStringDelegate(string value, IntPtr end, int radix); internal static PyLong_AsLongDelegate PyLong_AsLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyLong_AsLongDelegate(IntPtr value); + internal delegate int PyLong_AsLongDelegate(IntPtr value); internal static PyLong_AsUnsignedLongDelegate PyLong_AsUnsignedLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate uint PyLong_AsUnsignedLongDelegate(IntPtr value); + internal delegate uint PyLong_AsUnsignedLongDelegate(IntPtr value); internal static PyLong_AsLongLongDelegate PyLong_AsLongLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate long PyLong_AsLongLongDelegate(IntPtr value); + internal delegate long PyLong_AsLongLongDelegate(IntPtr value); internal static PyLong_AsUnsignedLongLongDelegate PyLong_AsUnsignedLongLong { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate ulong PyLong_AsUnsignedLongLongDelegate(IntPtr value); + internal delegate ulong PyLong_AsUnsignedLongLongDelegate(IntPtr value); internal static PyFloat_FromDoubleDelegate PyFloat_FromDouble { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyFloat_FromDoubleDelegate(double value); + internal delegate IntPtr PyFloat_FromDoubleDelegate(double value); internal static PyFloat_FromStringDelegate PyFloat_FromString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyFloat_FromStringDelegate(IntPtr value, IntPtr junk); + internal delegate IntPtr PyFloat_FromStringDelegate(IntPtr value, IntPtr junk); internal static PyFloat_AsDoubleDelegate PyFloat_AsDouble { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate double PyFloat_AsDoubleDelegate(IntPtr ob); + internal delegate double PyFloat_AsDoubleDelegate(IntPtr ob); internal static PyNumber_AddDelegate PyNumber_Add { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_AddDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_AddDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_SubtractDelegate PyNumber_Subtract { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_SubtractDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_SubtractDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_MultiplyDelegate PyNumber_Multiply { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_MultiplyDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_MultiplyDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_DivideDelegate PyNumber_Divide { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_DivideDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_DivideDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_AndDelegate PyNumber_And { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_AndDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_AndDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_XorDelegate PyNumber_Xor { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_XorDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_XorDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_OrDelegate PyNumber_Or { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_OrDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_OrDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_LshiftDelegate PyNumber_Lshift { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_LshiftDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_LshiftDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_RshiftDelegate PyNumber_Rshift { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_RshiftDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_RshiftDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_PowerDelegate PyNumber_Power { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_PowerDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_PowerDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_RemainderDelegate PyNumber_Remainder { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_RemainderDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_RemainderDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceAddDelegate PyNumber_InPlaceAdd { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceAddDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceAddDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceSubtractDelegate PyNumber_InPlaceSubtract { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceSubtractDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceSubtractDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceMultiplyDelegate PyNumber_InPlaceMultiply { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceMultiplyDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceMultiplyDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceDivideDelegate PyNumber_InPlaceDivide { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceDivideDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceDivideDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceAndDelegate PyNumber_InPlaceAnd { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceAndDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceAndDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceXorDelegate PyNumber_InPlaceXor { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceXorDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceXorDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceOrDelegate PyNumber_InPlaceOr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceOrDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceOrDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceLshiftDelegate PyNumber_InPlaceLshift { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceLshiftDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceLshiftDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceRshiftDelegate PyNumber_InPlaceRshift { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceRshiftDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceRshiftDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlacePowerDelegate PyNumber_InPlacePower { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlacePowerDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlacePowerDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_InPlaceRemainderDelegate PyNumber_InPlaceRemainder { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InPlaceRemainderDelegate(IntPtr o1, IntPtr o2); + internal delegate IntPtr PyNumber_InPlaceRemainderDelegate(IntPtr o1, IntPtr o2); internal static PyNumber_NegativeDelegate PyNumber_Negative { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_NegativeDelegate(IntPtr o1); + internal delegate IntPtr PyNumber_NegativeDelegate(IntPtr o1); internal static PyNumber_PositiveDelegate PyNumber_Positive { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_PositiveDelegate(IntPtr o1); + internal delegate IntPtr PyNumber_PositiveDelegate(IntPtr o1); internal static PyNumber_InvertDelegate PyNumber_Invert { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyNumber_InvertDelegate(IntPtr o1); + internal delegate IntPtr PyNumber_InvertDelegate(IntPtr o1); internal static PySequence_CheckDelegate PySequence_Check { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate bool PySequence_CheckDelegate(IntPtr pointer); + internal delegate bool PySequence_CheckDelegate(IntPtr pointer); internal static PySequence_GetItemDelegate PySequence_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_GetItemDelegate(IntPtr pointer, IntPtr index); + internal delegate IntPtr PySequence_GetItemDelegate(IntPtr pointer, IntPtr index); internal static PySequence_SetItemDelegate PySequence_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + internal delegate int PySequence_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); internal static PySequence_DelItemDelegate PySequence_DelItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_DelItemDelegate(IntPtr pointer, IntPtr index); + internal delegate int PySequence_DelItemDelegate(IntPtr pointer, IntPtr index); internal static PySequence_GetSliceDelegate PySequence_GetSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_GetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); + internal delegate IntPtr PySequence_GetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); internal static PySequence_SetSliceDelegate PySequence_SetSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_SetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2, IntPtr v); + internal delegate int PySequence_SetSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2, IntPtr v); internal static PySequence_DelSliceDelegate PySequence_DelSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_DelSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); + internal delegate int PySequence_DelSliceDelegate(IntPtr pointer, IntPtr i1, IntPtr i2); internal static _PySequence_SizeDelegate _PySequence_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PySequence_SizeDelegate(IntPtr pointer); + internal delegate IntPtr _PySequence_SizeDelegate(IntPtr pointer); internal static PySequence_ContainsDelegate PySequence_Contains { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_ContainsDelegate(IntPtr pointer, IntPtr item); + internal delegate int PySequence_ContainsDelegate(IntPtr pointer, IntPtr item); internal static PySequence_ConcatDelegate PySequence_Concat { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_ConcatDelegate(IntPtr pointer, IntPtr other); + internal delegate IntPtr PySequence_ConcatDelegate(IntPtr pointer, IntPtr other); internal static PySequence_RepeatDelegate PySequence_Repeat { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_RepeatDelegate(IntPtr pointer, IntPtr count); + internal delegate IntPtr PySequence_RepeatDelegate(IntPtr pointer, IntPtr count); internal static PySequence_IndexDelegate PySequence_Index { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySequence_IndexDelegate(IntPtr pointer, IntPtr item); + internal delegate int PySequence_IndexDelegate(IntPtr pointer, IntPtr item); internal static _PySequence_CountDelegate _PySequence_Count { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PySequence_CountDelegate(IntPtr pointer, IntPtr value); + internal delegate IntPtr _PySequence_CountDelegate(IntPtr pointer, IntPtr value); internal static PySequence_TupleDelegate PySequence_Tuple { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_TupleDelegate(IntPtr pointer); + internal delegate IntPtr PySequence_TupleDelegate(IntPtr pointer); internal static PySequence_ListDelegate PySequence_List { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySequence_ListDelegate(IntPtr pointer); + internal delegate IntPtr PySequence_ListDelegate(IntPtr pointer); internal static PyBytes_FromStringDelegate PyBytes_FromString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyBytes_FromStringDelegate(string op); + internal delegate IntPtr PyBytes_FromStringDelegate(string op); internal static _PyBytes_SizeDelegate _PyBytes_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyBytes_SizeDelegate(IntPtr op); + internal delegate IntPtr _PyBytes_SizeDelegate(IntPtr op); internal static _PyString_FromStringAndSizeDelegate _PyString_FromStringAndSize { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyString_FromStringAndSizeDelegate( + internal delegate IntPtr _PyString_FromStringAndSizeDelegate( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, IntPtr size ); @@ -2724,22 +2725,22 @@ IntPtr size internal static PyUnicode_FromStringAndSizeDelegate PyUnicode_FromStringAndSize { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_FromStringAndSizeDelegate(IntPtr value, IntPtr size); + internal delegate IntPtr PyUnicode_FromStringAndSizeDelegate(IntPtr value, IntPtr size); internal static PyUnicode_FromObjectDelegate PyUnicode_FromObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_FromObjectDelegate(IntPtr ob); + internal delegate IntPtr PyUnicode_FromObjectDelegate(IntPtr ob); internal static PyUnicode_FromEncodedObjectDelegate PyUnicode_FromEncodedObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_FromEncodedObjectDelegate(IntPtr ob, IntPtr enc, IntPtr err); + internal delegate IntPtr PyUnicode_FromEncodedObjectDelegate(IntPtr ob, IntPtr enc, IntPtr err); internal static PyUnicode_FromKindAndDataDelegate PyUnicode_FromKindAndData { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_FromKindAndDataDelegate( + internal delegate IntPtr PyUnicode_FromKindAndDataDelegate( int kind, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, IntPtr size @@ -2748,237 +2749,237 @@ IntPtr size internal static _PyUnicode_GetSizeDelegate _PyUnicode_GetSize { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyUnicode_GetSizeDelegate(IntPtr ob); + internal delegate IntPtr _PyUnicode_GetSizeDelegate(IntPtr ob); internal static PyUnicode_AsUnicodeDelegate PyUnicode_AsUnicode { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_AsUnicodeDelegate(IntPtr ob); + internal delegate IntPtr PyUnicode_AsUnicodeDelegate(IntPtr ob); internal static PyUnicode_FromOrdinalDelegate PyUnicode_FromOrdinal { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyUnicode_FromOrdinalDelegate(int c); + internal delegate IntPtr PyUnicode_FromOrdinalDelegate(int c); internal static PyDict_NewDelegate PyDict_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_NewDelegate(); + internal delegate IntPtr PyDict_NewDelegate(); internal static PyDictProxy_NewDelegate PyDictProxy_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDictProxy_NewDelegate(IntPtr dict); + internal delegate IntPtr PyDictProxy_NewDelegate(IntPtr dict); internal static PyDict_GetItemDelegate PyDict_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_GetItemDelegate(IntPtr pointer, IntPtr key); + internal delegate IntPtr PyDict_GetItemDelegate(IntPtr pointer, IntPtr key); internal static PyDict_GetItemStringDelegate PyDict_GetItemString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_GetItemStringDelegate(IntPtr pointer, string key); + internal delegate IntPtr PyDict_GetItemStringDelegate(IntPtr pointer, string key); internal static PyDict_SetItemDelegate PyDict_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyDict_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); + internal delegate int PyDict_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); internal static PyDict_SetItemStringDelegate PyDict_SetItemString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyDict_SetItemStringDelegate(IntPtr pointer, string key, IntPtr value); + internal delegate int PyDict_SetItemStringDelegate(IntPtr pointer, string key, IntPtr value); internal static PyDict_DelItemDelegate PyDict_DelItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyDict_DelItemDelegate(IntPtr pointer, IntPtr key); + internal delegate int PyDict_DelItemDelegate(IntPtr pointer, IntPtr key); internal static PyDict_DelItemStringDelegate PyDict_DelItemString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyDict_DelItemStringDelegate(IntPtr pointer, string key); + internal delegate int PyDict_DelItemStringDelegate(IntPtr pointer, string key); internal static PyMapping_HasKeyDelegate PyMapping_HasKey { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyMapping_HasKeyDelegate(IntPtr pointer, IntPtr key); + internal delegate int PyMapping_HasKeyDelegate(IntPtr pointer, IntPtr key); internal static PyDict_KeysDelegate PyDict_Keys { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_KeysDelegate(IntPtr pointer); + internal delegate IntPtr PyDict_KeysDelegate(IntPtr pointer); internal static PyDict_ValuesDelegate PyDict_Values { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_ValuesDelegate(IntPtr pointer); + internal delegate IntPtr PyDict_ValuesDelegate(IntPtr pointer); internal static PyDict_ItemsDelegate PyDict_Items { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_ItemsDelegate(IntPtr pointer); + internal delegate IntPtr PyDict_ItemsDelegate(IntPtr pointer); internal static PyDict_CopyDelegate PyDict_Copy { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyDict_CopyDelegate(IntPtr pointer); + internal delegate IntPtr PyDict_CopyDelegate(IntPtr pointer); internal static PyDict_UpdateDelegate PyDict_Update { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyDict_UpdateDelegate(IntPtr pointer, IntPtr other); + internal delegate int PyDict_UpdateDelegate(IntPtr pointer, IntPtr other); internal static PyDict_ClearDelegate PyDict_Clear { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyDict_ClearDelegate(IntPtr pointer); + internal delegate void PyDict_ClearDelegate(IntPtr pointer); internal static _PyDict_SizeDelegate _PyDict_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyDict_SizeDelegate(IntPtr pointer); + internal delegate IntPtr _PyDict_SizeDelegate(IntPtr pointer); internal static PyList_NewDelegate PyList_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyList_NewDelegate(IntPtr size); + internal delegate IntPtr PyList_NewDelegate(IntPtr size); internal static PyList_AsTupleDelegate PyList_AsTuple { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyList_AsTupleDelegate(IntPtr pointer); + internal delegate IntPtr PyList_AsTupleDelegate(IntPtr pointer); internal static PyList_GetItemDelegate PyList_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyList_GetItemDelegate(IntPtr pointer, IntPtr index); + internal delegate IntPtr PyList_GetItemDelegate(IntPtr pointer, IntPtr index); internal static PyList_SetItemDelegate PyList_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + internal delegate int PyList_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); internal static PyList_InsertDelegate PyList_Insert { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_InsertDelegate(IntPtr pointer, IntPtr index, IntPtr value); + internal delegate int PyList_InsertDelegate(IntPtr pointer, IntPtr index, IntPtr value); internal static PyList_AppendDelegate PyList_Append { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_AppendDelegate(IntPtr pointer, IntPtr value); + internal delegate int PyList_AppendDelegate(IntPtr pointer, IntPtr value); internal static PyList_ReverseDelegate PyList_Reverse { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_ReverseDelegate(IntPtr pointer); + internal delegate int PyList_ReverseDelegate(IntPtr pointer); internal static PyList_SortDelegate PyList_Sort { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_SortDelegate(IntPtr pointer); + internal delegate int PyList_SortDelegate(IntPtr pointer); internal static PyList_GetSliceDelegate PyList_GetSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyList_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); + internal delegate IntPtr PyList_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); internal static PyList_SetSliceDelegate PyList_SetSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyList_SetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value); + internal delegate int PyList_SetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end, IntPtr value); internal static _PyList_SizeDelegate _PyList_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyList_SizeDelegate(IntPtr pointer); + internal delegate IntPtr _PyList_SizeDelegate(IntPtr pointer); internal static PyTuple_NewDelegate PyTuple_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyTuple_NewDelegate(IntPtr size); + internal delegate IntPtr PyTuple_NewDelegate(IntPtr size); internal static PyTuple_GetItemDelegate PyTuple_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyTuple_GetItemDelegate(IntPtr pointer, IntPtr index); + internal delegate IntPtr PyTuple_GetItemDelegate(IntPtr pointer, IntPtr index); internal static PyTuple_SetItemDelegate PyTuple_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyTuple_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); + internal delegate int PyTuple_SetItemDelegate(IntPtr pointer, IntPtr index, IntPtr value); internal static PyTuple_GetSliceDelegate PyTuple_GetSlice { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyTuple_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); + internal delegate IntPtr PyTuple_GetSliceDelegate(IntPtr pointer, IntPtr start, IntPtr end); internal static _PyTuple_SizeDelegate _PyTuple_Size { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyTuple_SizeDelegate(IntPtr pointer); + internal delegate IntPtr _PyTuple_SizeDelegate(IntPtr pointer); internal static PyIter_NextDelegate PyIter_Next { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyIter_NextDelegate(IntPtr pointer); + internal delegate IntPtr PyIter_NextDelegate(IntPtr pointer); internal static PyModule_NewDelegate PyModule_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyModule_NewDelegate(string name); + internal delegate IntPtr PyModule_NewDelegate(string name); internal static PyModule_GetNameDelegate PyModule_GetName { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate string PyModule_GetNameDelegate(IntPtr module); + internal delegate string PyModule_GetNameDelegate(IntPtr module); internal static PyModule_GetDictDelegate PyModule_GetDict { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyModule_GetDictDelegate(IntPtr module); + internal delegate IntPtr PyModule_GetDictDelegate(IntPtr module); internal static PyModule_GetFilenameDelegate PyModule_GetFilename { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate string PyModule_GetFilenameDelegate(IntPtr module); + internal delegate string PyModule_GetFilenameDelegate(IntPtr module); internal static PyModule_Create2Delegate PyModule_Create2 { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyModule_Create2Delegate(IntPtr module, int apiver); + internal delegate IntPtr PyModule_Create2Delegate(IntPtr module, int apiver); internal static PyImport_ImportDelegate PyImport_Import { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_ImportDelegate(IntPtr name); + internal delegate IntPtr PyImport_ImportDelegate(IntPtr name); internal static PyImport_ImportModuleDelegate PyImport_ImportModule { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_ImportModuleDelegate(string name); + internal delegate IntPtr PyImport_ImportModuleDelegate(string name); internal static PyImport_ReloadModuleDelegate PyImport_ReloadModule { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_ReloadModuleDelegate(IntPtr module); + internal delegate IntPtr PyImport_ReloadModuleDelegate(IntPtr module); internal static PyImport_AddModuleDelegate PyImport_AddModule { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_AddModuleDelegate(string name); + internal delegate IntPtr PyImport_AddModuleDelegate(string name); internal static PyImport_GetModuleDictDelegate PyImport_GetModuleDict { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyImport_GetModuleDictDelegate(); + internal delegate IntPtr PyImport_GetModuleDictDelegate(); internal static PySys_SetArgvExDelegate PySys_SetArgvEx { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PySys_SetArgvExDelegate( + internal delegate void PySys_SetArgvExDelegate( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, int updatepath @@ -2987,162 +2988,162 @@ int updatepath internal static PySys_GetObjectDelegate PySys_GetObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PySys_GetObjectDelegate(string name); + internal delegate IntPtr PySys_GetObjectDelegate(string name); internal static PySys_SetObjectDelegate PySys_SetObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PySys_SetObjectDelegate(string name, IntPtr ob); + internal delegate int PySys_SetObjectDelegate(string name, IntPtr ob); internal static PyType_ModifiedDelegate PyType_Modified { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyType_ModifiedDelegate(IntPtr type); + internal delegate void PyType_ModifiedDelegate(IntPtr type); internal static PyType_IsSubtypeDelegate PyType_IsSubtype { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate bool PyType_IsSubtypeDelegate(IntPtr t1, IntPtr t2); + internal delegate bool PyType_IsSubtypeDelegate(IntPtr t1, IntPtr t2); internal static PyType_GenericNewDelegate PyType_GenericNew { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyType_GenericNewDelegate(IntPtr type, IntPtr args, IntPtr kw); + internal delegate IntPtr PyType_GenericNewDelegate(IntPtr type, IntPtr args, IntPtr kw); internal static PyType_GenericAllocDelegate PyType_GenericAlloc { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyType_GenericAllocDelegate(IntPtr type, IntPtr n); + internal delegate IntPtr PyType_GenericAllocDelegate(IntPtr type, IntPtr n); internal static PyType_ReadyDelegate PyType_Ready { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyType_ReadyDelegate(IntPtr type); + internal delegate int PyType_ReadyDelegate(IntPtr type); internal static _PyType_LookupDelegate _PyType_Lookup { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyType_LookupDelegate(IntPtr type, IntPtr name); + internal delegate IntPtr _PyType_LookupDelegate(IntPtr type, IntPtr name); internal static PyObject_GenericGetAttrDelegate PyObject_GenericGetAttr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyObject_GenericGetAttrDelegate(IntPtr obj, IntPtr name); + internal delegate IntPtr PyObject_GenericGetAttrDelegate(IntPtr obj, IntPtr name); internal static PyObject_GenericSetAttrDelegate PyObject_GenericSetAttr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyObject_GenericSetAttrDelegate(IntPtr obj, IntPtr name, IntPtr value); + internal delegate int PyObject_GenericSetAttrDelegate(IntPtr obj, IntPtr name, IntPtr value); internal static _PyObject_GetDictPtrDelegate _PyObject_GetDictPtr { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr _PyObject_GetDictPtrDelegate(IntPtr obj); + internal delegate IntPtr _PyObject_GetDictPtrDelegate(IntPtr obj); internal static PyObject_GC_DelDelegate PyObject_GC_Del { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyObject_GC_DelDelegate(IntPtr tp); + internal delegate void PyObject_GC_DelDelegate(IntPtr tp); internal static PyObject_GC_TrackDelegate PyObject_GC_Track { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyObject_GC_TrackDelegate(IntPtr tp); + internal delegate void PyObject_GC_TrackDelegate(IntPtr tp); internal static PyObject_GC_UnTrackDelegate PyObject_GC_UnTrack { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyObject_GC_UnTrackDelegate(IntPtr tp); + internal delegate void PyObject_GC_UnTrackDelegate(IntPtr tp); internal static PyMem_MallocDelegate PyMem_Malloc { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMem_MallocDelegate(IntPtr size); + internal delegate IntPtr PyMem_MallocDelegate(IntPtr size); internal static PyMem_ReallocDelegate PyMem_Realloc { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMem_ReallocDelegate(IntPtr ptr, IntPtr size); + internal delegate IntPtr PyMem_ReallocDelegate(IntPtr ptr, IntPtr size); internal static PyMem_FreeDelegate PyMem_Free { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyMem_FreeDelegate(IntPtr ptr); + internal delegate void PyMem_FreeDelegate(IntPtr ptr); internal static PyErr_SetStringDelegate PyErr_SetString { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_SetStringDelegate(IntPtr ob, string message); + internal delegate void PyErr_SetStringDelegate(IntPtr ob, string message); internal static PyErr_SetObjectDelegate PyErr_SetObject { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_SetObjectDelegate(IntPtr ob, IntPtr message); + internal delegate void PyErr_SetObjectDelegate(IntPtr ob, IntPtr message); internal static PyErr_SetFromErrnoDelegate PyErr_SetFromErrno { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyErr_SetFromErrnoDelegate(IntPtr ob); + internal delegate IntPtr PyErr_SetFromErrnoDelegate(IntPtr ob); internal static PyErr_SetNoneDelegate PyErr_SetNone { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_SetNoneDelegate(IntPtr ob); + internal delegate void PyErr_SetNoneDelegate(IntPtr ob); internal static PyErr_ExceptionMatchesDelegate PyErr_ExceptionMatches { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyErr_ExceptionMatchesDelegate(IntPtr exception); + internal delegate int PyErr_ExceptionMatchesDelegate(IntPtr exception); internal static PyErr_GivenExceptionMatchesDelegate PyErr_GivenExceptionMatches { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate int PyErr_GivenExceptionMatchesDelegate(IntPtr ob, IntPtr val); + internal delegate int PyErr_GivenExceptionMatchesDelegate(IntPtr ob, IntPtr val); internal static PyErr_NormalizeExceptionDelegate PyErr_NormalizeException { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_NormalizeExceptionDelegate(IntPtr ob, IntPtr val, IntPtr tb); + internal delegate void PyErr_NormalizeExceptionDelegate(IntPtr ob, IntPtr val, IntPtr tb); internal static PyErr_OccurredDelegate PyErr_Occurred { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyErr_OccurredDelegate(); + internal delegate IntPtr PyErr_OccurredDelegate(); internal static PyErr_FetchDelegate PyErr_Fetch { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_FetchDelegate(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + internal delegate void PyErr_FetchDelegate(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); internal static PyErr_RestoreDelegate PyErr_Restore { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_RestoreDelegate(IntPtr ob, IntPtr val, IntPtr tb); + internal delegate void PyErr_RestoreDelegate(IntPtr ob, IntPtr val, IntPtr tb); internal static PyErr_ClearDelegate PyErr_Clear { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_ClearDelegate(); + internal delegate void PyErr_ClearDelegate(); internal static PyErr_PrintDelegate PyErr_Print { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate void PyErr_PrintDelegate(); + internal delegate void PyErr_PrintDelegate(); internal static PyMethod_SelfDelegate PyMethod_Self { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMethod_SelfDelegate(IntPtr ob); + internal delegate IntPtr PyMethod_SelfDelegate(IntPtr ob); internal static PyMethod_FunctionDelegate PyMethod_Function { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMethod_FunctionDelegate(IntPtr ob); + internal delegate IntPtr PyMethod_FunctionDelegate(IntPtr ob); internal static PyMethod_NewDelegate PyMethod_New { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - public delegate IntPtr PyMethod_NewDelegate(IntPtr func, IntPtr self); + internal delegate IntPtr PyMethod_NewDelegate(IntPtr func, IntPtr self); // end of PY3 enum Py2 { } @@ -3150,7 +3151,7 @@ enum Py2 { } } #if NETFX - class RuntimeInformation{ + static class RuntimeInformation{ public static bool IsOSPlatform(OSPlatform platform){return platform == OSPlatform.Windows;} } diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index db4c7e748..9f657e757 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -13,8 +13,7 @@ public interface IGetAttr { static class SlotOverrides { public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { if (!Runtime.PyString_Check(key)) { - IntPtr genericResult = Runtime.PyObject_GenericGetAttr(ob, key); - return genericResult; + return Runtime.PyObject_GenericGetAttr(ob, key); } Exceptions.Clear(); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index c8e0df7c0..3f769ee56 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -11,7 +11,7 @@ namespace Python.Runtime /// The TypeManager class is responsible for building binary-compatible /// Python type objects that are implemented in managed code. /// - internal class TypeManager + internal static class TypeManager { private static BindingFlags tbFlags; private static Dictionary cache; diff --git a/tools/geninterop/geninterop.py b/tools/geninterop/geninterop.py index f0c07bbc9..6a5399a7c 100644 --- a/tools/geninterop/geninterop.py +++ b/tools/geninterop/geninterop.py @@ -225,7 +225,7 @@ def gen_interop_code(members): namespace Python.Runtime {{ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset{1} + internal static class TypeOffset{1} {{ // Auto-generated from PyHeapTypeObject in Python.h """.format(filename, PY_VER) From 5f49fb4b2c645817718f63386cac9346a8d8f2eb Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 12:57:35 -0700 Subject: [PATCH 068/240] removed dead BasicSubType code from TypeManager --- src/runtime/typemanager.cs | 41 -------------------------------------- 1 file changed, 41 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 3f769ee56..37ba5bd5b 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -425,47 +425,6 @@ internal static IntPtr CreateMetaType(Type impl) return type; } - - internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) - { - // Utility to create a subtype of a std Python type, but with - // a managed type able to override implementation - - IntPtr type = AllocateTypeObject(name); - //Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize); - //Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); - - //IntPtr offset = (IntPtr)ObjectOffset.ob_dict; - //Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); - - //IntPtr dc = Runtime.PyDict_Copy(dict); - //Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc); - - Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); - Runtime.XIncref(base_); - - int flags = TypeFlags.Default; - flags |= TypeFlags.Managed; - flags |= TypeFlags.HeapType; - flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); - - CopySlot(base_, type, TypeOffset.tp_traverse); - CopySlot(base_, type, TypeOffset.tp_clear); - CopySlot(base_, type, TypeOffset.tp_is_gc); - - InitializeSlots(type, impl); - - Runtime.PyType_Ready(type); - - IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); - IntPtr mod = Runtime.PyString_FromString("CLR"); - Runtime.PyDict_SetItemString(tp_dict, "__module__", mod); - - return type; - } - - /// /// Utility method to allocate a type object & do basic initialization. /// From b4eb7957137bdc425be221a9ad9538c498d785fb Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 13:03:27 -0700 Subject: [PATCH 069/240] marked a bunch of test classes as static --- src/embed_tests/TestDomainReload.cs | 2 +- src/embed_tests/TestPyFloat.cs | 4 +--- src/embed_tests/TestPyTuple.cs | 4 +--- src/embed_tests/TestTypeManager.cs | 2 +- src/testing/arraytest.cs | 2 +- src/testing/classtest.cs | 2 +- src/testing/generictest.cs | 10 +++++----- src/testing/moduletest.cs | 2 +- src/testing/subclasstest.cs | 2 +- src/testing/threadtest.cs | 2 +- 10 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/embed_tests/TestDomainReload.cs b/src/embed_tests/TestDomainReload.cs index b162d4eb0..a1362a426 100644 --- a/src/embed_tests/TestDomainReload.cs +++ b/src/embed_tests/TestDomainReload.cs @@ -14,7 +14,7 @@ #if !NETSTANDARD && !NETCOREAPP namespace Python.EmbeddingTest { - class TestDomainReload + static class TestDomainReload { /// /// Test that the python runtime can survive a C# domain reload without crashing. diff --git a/src/embed_tests/TestPyFloat.cs b/src/embed_tests/TestPyFloat.cs index f2c85a77f..0bb56d761 100644 --- a/src/embed_tests/TestPyFloat.cs +++ b/src/embed_tests/TestPyFloat.cs @@ -4,9 +4,7 @@ namespace Python.EmbeddingTest { - /// - /// PyFloat implementation isn't complete, thus tests aren't complete. - /// + // PyFloat implementation isn't complete, thus tests aren't complete. public class TestPyFloat { [OneTimeSetUp] diff --git a/src/embed_tests/TestPyTuple.cs b/src/embed_tests/TestPyTuple.cs index 362251049..79a1d90f2 100644 --- a/src/embed_tests/TestPyTuple.cs +++ b/src/embed_tests/TestPyTuple.cs @@ -153,9 +153,7 @@ public void TestNewPyTupleFromPyTuple() Assert.IsInstanceOf(typeof(PyTuple), t); } - /// - /// TODO: Should this throw ArgumentError instead? - /// + // TODO: Should this throw ArgumentError instead? [Test] public void TestInvalidAsTuple() { diff --git a/src/embed_tests/TestTypeManager.cs b/src/embed_tests/TestTypeManager.cs index a4ef86913..48ebef568 100644 --- a/src/embed_tests/TestTypeManager.cs +++ b/src/embed_tests/TestTypeManager.cs @@ -4,7 +4,7 @@ namespace Python.EmbeddingTest { - class TestTypeManager + static class TestTypeManager { [SetUp] public static void Init() diff --git a/src/testing/arraytest.cs b/src/testing/arraytest.cs index 946684962..7e79701e6 100644 --- a/src/testing/arraytest.cs +++ b/src/testing/arraytest.cs @@ -297,7 +297,7 @@ public MultiDimensionalArrayTest() } - public class ArrayConversionTest + public static class ArrayConversionTest { public static Spam[] EchoRange(Spam[] items) { diff --git a/src/testing/classtest.cs b/src/testing/classtest.cs index 68c0d8c55..797959bc6 100644 --- a/src/testing/classtest.cs +++ b/src/testing/classtest.cs @@ -5,7 +5,7 @@ namespace Python.Test /// /// Supports CLR class unit tests. /// - public class ClassTest + public static class ClassTest { public static ArrayList GetArrayList() { diff --git a/src/testing/generictest.cs b/src/testing/generictest.cs index 1e9c71ac6..51639cf39 100644 --- a/src/testing/generictest.cs +++ b/src/testing/generictest.cs @@ -36,27 +36,27 @@ public DerivedFromOpenGeneric(int arg1, V arg2, W arg3) : base(arg1, arg2) } - public class GenericNameTest1 + public static class GenericNameTest1 { public static int value = 0; } - public class GenericNameTest1 + public static class GenericNameTest1 { public static int value = 1; } - public class GenericNameTest1 + public static class GenericNameTest1 { public static int value = 2; } - public class GenericNameTest2 + public static class GenericNameTest2 { public static int value = 1; } - public class GenericNameTest2 + public static class GenericNameTest2 { public static int value = 2; } diff --git a/src/testing/moduletest.cs b/src/testing/moduletest.cs index 2df5269f3..820928279 100644 --- a/src/testing/moduletest.cs +++ b/src/testing/moduletest.cs @@ -4,7 +4,7 @@ namespace Python.Test { - public class ModuleTest + public static class ModuleTest { private static Thread _thread; diff --git a/src/testing/subclasstest.cs b/src/testing/subclasstest.cs index 9817d865e..772023591 100644 --- a/src/testing/subclasstest.cs +++ b/src/testing/subclasstest.cs @@ -74,7 +74,7 @@ public void SomeMethod() } } - public class FunctionsTest + public static class FunctionsTest { public static string test_foo(IInterfaceTest x) { diff --git a/src/testing/threadtest.cs b/src/testing/threadtest.cs index 2825c3fef..83f1c392b 100644 --- a/src/testing/threadtest.cs +++ b/src/testing/threadtest.cs @@ -6,7 +6,7 @@ namespace Python.Test /// /// Supports CLR threading / reentrant unit tests. /// - public class ThreadTest + public static class ThreadTest { private static PyObject module; From 88bbb0b1c6268edbdfada00e417bda8da221e3f5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 13:05:28 -0700 Subject: [PATCH 070/240] marked clrModule as static --- src/clrmodule/ClrModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clrmodule/ClrModule.cs b/src/clrmodule/ClrModule.cs index de1b6ee77..4665e6010 100644 --- a/src/clrmodule/ClrModule.cs +++ b/src/clrmodule/ClrModule.cs @@ -28,7 +28,7 @@ using System.Runtime.InteropServices; using RGiesecke.DllExport; -public class clrModule +public static class clrModule { [DllExport("PyInit_clr", CallingConvention.StdCall)] public static IntPtr PyInit_clr() From b75fba51e99facd38df9a9598aa51570e012d3db Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 13:14:55 -0700 Subject: [PATCH 071/240] disabled test passing dynamic object --- src/embed_tests/TestPassDynamic.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/embed_tests/TestPassDynamic.cs b/src/embed_tests/TestPassDynamic.cs index bcef90f2a..2e0c8ba8b 100644 --- a/src/embed_tests/TestPassDynamic.cs +++ b/src/embed_tests/TestPassDynamic.cs @@ -20,6 +20,7 @@ public void Dispose() } [Test] + [Ignore("Passing dynamic objects is no implemented. https://github.com/pythonnet/pythonnet/issues/952")] public void ExpandoProperties() { dynamic expando = new ExpandoObject(); expando.test = 42; From 1e479a6263325baeee0147725f32741bd3a81dc4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 14:03:43 -0700 Subject: [PATCH 072/240] minor fix --- src/embed_tests/TestCustomArgMarshal.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 95f8713c4..869809ee9 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -77,8 +77,7 @@ public void ConvertibleFromPython() { [Test] public void ConvertibleFromPythonBypass() { using (Py.GIL()) { - bool ok = false; - void Accept(ConvertibleFromPython obj) => ok = true; + void Accept(ConvertibleFromPython obj) { } dynamic callWithInt = PythonEngine.Eval("lambda f: f('42')"); Assert.Throws(() => callWithInt(new Action(Accept)), From 813e7eaf4d29a555a757b3c5f7a4cd1333aa0df2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 14:04:15 -0700 Subject: [PATCH 073/240] added test for calling base C# method when additional Python base class was added --- src/embed_tests/Inheritance.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index 07c373ad6..d721e9571 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -68,6 +68,16 @@ public void InheritedFromInheritedIsInstance() { Assert.IsTrue(properlyInherited); } } + + [Test] + public void CanCallInheritedMethodWithPythonBase() { + var instance = new Inherited(); + using (Py.GIL()) { + dynamic callBase = PythonEngine.Eval($"lambda o: o.{nameof(PythonWrapperBase.WrapperBaseMethod)}()"); + string result = (string)callBase(instance); + Assert.AreEqual(result, nameof(PythonWrapperBase.WrapperBaseMethod)); + } + } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] @@ -83,7 +93,9 @@ class DefaultBaseTypeAttribute : BaseTypeAttributeBase { } [DefaultBaseType] - public class PythonWrapperBase { } + public class PythonWrapperBase { + public string WrapperBaseMethod() => nameof(WrapperBaseMethod); + } [CustomBaseType] public class InheritanceTestBaseClassWrapper : PythonWrapperBase { From 390a8d48001bc41cdefdc5800cb0f9955be26fdd Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 14:04:49 -0700 Subject: [PATCH 074/240] fixed inability to invoke C# methods from base class when Python base is specified --- src/runtime/typemanager.cs | 47 +++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 37ba5bd5b..ab17c096b 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -136,11 +136,16 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); } - IntPtr base_ = GetBaseType(clrType); + IntPtr base_ = GetBaseType(clrType, out IntPtr bases); if (base_ != IntPtr.Zero) { Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.XIncref(base_); + + if (bases != IntPtr.Zero) { + Marshal.WriteIntPtr(type, TypeOffset.tp_bases, bases); + Runtime.XIncref(bases); + } } int flags = TypeFlags.Default; @@ -230,8 +235,23 @@ static string CleanupFullName(string fullTypeName) return name; } - static IntPtr GetBaseType(Type clrType) + static IntPtr GetBaseType(Type clrType, out IntPtr baseTypes) { + baseTypes = IntPtr.Zero; + if (clrType == typeof(Exception)) + { + return Exceptions.Exception; + } + + var bases = new List(); + + // .NET base class must always come first + if (clrType.BaseType != null) + { + ClassBase bc = ClassManager.GetClass(clrType.BaseType); + bases.Add(bc.pyHandle); + } + var baseOverride = Util.GetLatestAttribute(clrType); IntPtr handle = baseOverride?.BaseType(clrType) ?? IntPtr.Zero; if (handle != IntPtr.Zero) { @@ -239,20 +259,21 @@ static IntPtr GetBaseType(Type clrType) throw new InvalidProgramException("The specified base Python type can not be inherited from"); } - return handle; + bases.Add(handle); } - if (clrType == typeof(Exception)) - { - return Exceptions.Exception; - } - if (clrType.BaseType != null) - { - ClassBase bc = ClassManager.GetClass(clrType.BaseType); - return bc.pyHandle; + switch (bases.Count) { + case 0: + return IntPtr.Zero; + case 1: + return bases[0]; + default: + baseTypes = Runtime.PyTuple_New(bases.Count); + for (int baseIndex = 0; baseIndex < bases.Count; baseIndex++) { + Runtime.PyTuple_SetItem(baseTypes, baseIndex, bases[baseIndex]); + } + return bases[0]; } - - return IntPtr.Zero; } internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) From fe61a0a1931d45e46dc00db9bf7d374c019903b9 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 15:17:20 -0700 Subject: [PATCH 075/240] when constructing a Python wrapper for .NET type, check, that everything went well --- src/runtime/classmanager.cs | 2 +- src/runtime/typemanager.cs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index 0b084a49d..9aaa75a59 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -132,8 +132,8 @@ private static void InitClassBase(Type type, ClassBase impl) // managed type, filling the Python type slots with thunks that // point to the managed methods providing the implementation. - IntPtr tp = TypeManager.GetTypeHandle(impl, type); + Exceptions.ErrorCheck(tp); impl.tpHandle = tp; // Finally, initialize the class __dict__ and return the object. diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index ab17c096b..14c170eaf 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -159,7 +159,10 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) // that the type of the new type must PyType_Type at the time we // call this, else PyType_Ready will skip some slot initialization. - Runtime.PyType_Ready(type); + if (Runtime.PyType_Ready(type) != 0) + { + return IntPtr.Zero; + } IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); string mn = clrType.Namespace ?? ""; @@ -342,6 +345,10 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr // create the new ManagedType and python type ClassBase subClass = ClassManager.GetClass(subType); IntPtr py_type = GetTypeHandle(subClass, subType); + if (py_type == IntPtr.Zero) + { + return IntPtr.Zero; + } // 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. From c0ffc298e89919cebaa9d50b43acd8edb605435c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 21:59:27 -0700 Subject: [PATCH 076/240] enable expanding set of marshaling conversions via PyObjectConversions added sample TupleCodec (only supporting ValueTuple) --- src/embed_tests/Codecs.cs | 86 +++++++++++++++ src/runtime/Codecs/TupleCodecs.cs | 114 ++++++++++++++++++++ src/runtime/converter.cs | 29 +++-- src/runtime/converterextensions.cs | 163 +++++++++++++++++++++++++++++ src/runtime/pythonengine.cs | 2 + src/runtime/runtime.cs | 2 + 6 files changed, 389 insertions(+), 7 deletions(-) create mode 100644 src/embed_tests/Codecs.cs create mode 100644 src/runtime/Codecs/TupleCodecs.cs create mode 100644 src/runtime/converterextensions.cs diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs new file mode 100644 index 000000000..a3db1dc5e --- /dev/null +++ b/src/embed_tests/Codecs.cs @@ -0,0 +1,86 @@ +namespace Python.EmbeddingTest { + using System; + using System.Collections.Generic; + using System.Text; + using NUnit.Framework; + using Python.Runtime; + using Python.Runtime.Codecs; + + public class Codecs { + [SetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [TearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + + [Test] + public void ConversionsGeneric() { + ConversionsGeneric, ValueTuple>(); + } + + static void ConversionsGeneric() { + TupleCodec.Register(); + var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); + T restored = default; + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + void Accept(T value) => restored = value; + var accept = new Action(Accept).ToPython(); + scope.Set(nameof(tuple), tuple); + scope.Set(nameof(accept), accept); + scope.Exec($"{nameof(accept)}({nameof(tuple)})"); + Assert.AreEqual(expected: tuple, actual: restored); + } + } + + [Test] + public void ConversionsObject() { + ConversionsGeneric, ValueTuple>(); + } + static void ConversionsObject() { + TupleCodec.Register(); + var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); + T restored = default; + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + void Accept(object value) => restored = (T)value; + var accept = new Action(Accept).ToPython(); + scope.Set(nameof(tuple), tuple); + scope.Set(nameof(accept), accept); + scope.Exec($"{nameof(accept)}({nameof(tuple)})"); + Assert.AreEqual(expected: tuple, actual: restored); + } + } + + [Test] + public void TupleRoundtripObject() { + TupleRoundtripObject, ValueTuple>(); + } + static void TupleRoundtripObject() { + var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); + using (Py.GIL()) { + var pyTuple = TupleCodec.Instance.TryEncode(tuple); + Assert.IsTrue(TupleCodec.Instance.TryDecode(pyTuple, out object restored)); + Assert.AreEqual(expected: tuple, actual: restored); + } + } + + [Test] + public void TupleRoundtripGeneric() { + TupleRoundtripGeneric, ValueTuple>(); + } + + static void TupleRoundtripGeneric() { + var tuple = Activator.CreateInstance(typeof(T), 42, "42", new object()); + using (Py.GIL()) { + var pyTuple = TupleCodec.Instance.TryEncode(tuple); + Assert.IsTrue(TupleCodec.Instance.TryDecode(pyTuple, out T restored)); + Assert.AreEqual(expected: tuple, actual: restored); + } + } + } +} diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs new file mode 100644 index 000000000..527529bf6 --- /dev/null +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -0,0 +1,114 @@ +namespace Python.Runtime.Codecs { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + + public sealed class TupleCodec : IPyObjectEncoder, IPyObjectDecoder { + TupleCodec() { } + public static TupleCodec Instance { get; } = new TupleCodec(); + + public bool CanEncode(Type type) + => type.Namespace == typeof(TTuple).Namespace && type.Name.StartsWith(typeof(TTuple).Name + '`') + || type == typeof(object) || type == typeof(TTuple); + + public PyObject TryEncode(object value) { + if (value == null) return null; + + var tupleType = value.GetType(); + if (tupleType == typeof(object)) return null; + if (!this.CanEncode(tupleType)) return null; + if (tupleType == typeof(TTuple)) return new PyTuple(); + + long fieldCount = tupleType.GetGenericArguments().Length; + var tuple = Runtime.PyTuple_New(fieldCount); + Exceptions.ErrorCheck(tuple); + int fieldIndex = 0; + foreach (FieldInfo field in tupleType.GetFields()) { + var item = field.GetValue(value); + IntPtr pyItem = Converter.ToPython(item); + Runtime.XIncref(pyItem); + Runtime.PyTuple_SetItem(tuple, fieldIndex, pyItem); + fieldIndex++; + } + return new PyTuple(Runtime.SelfIncRef(tuple)); + } + + public bool CanDecode(PyObject objectType, Type targetType) + => objectType.Handle == Runtime.PyTuple && this.CanEncode(targetType); + + public bool TryDecode(PyObject pyObj, out T value) { + if (pyObj == null) throw new ArgumentNullException(nameof(pyObj)); + + value = default; + + if (!Runtime.PyTuple_Check(pyObj.Handle)) return false; + + if (typeof(T) == typeof(object)) { + bool converted = Decode(pyObj, out object result); + if (converted) { + value = (T)result; + return true; + } + + return false; + } + + var itemTypes = typeof(T).GetGenericArguments(); + long itemCount = Runtime.PyTuple_Size(pyObj.Handle); + if (itemTypes.Length != itemCount) return false; + + if (itemCount == 0) { + value = (T)EmptyTuple; + return true; + } + + var elements = new object[itemCount]; + for (int itemIndex = 0; itemIndex < itemTypes.Length; itemIndex++) { + IntPtr pyItem = Runtime.PyTuple_GetItem(pyObj.Handle, itemIndex); + if (!Converter.ToManaged(pyItem, itemTypes[itemIndex], out elements[itemIndex], setError: false)) { + return false; + } + } + var factory = tupleCreate[itemCount].MakeGenericMethod(itemTypes); + value = (T)factory.Invoke(null, elements); + return true; + } + + static bool Decode(PyObject tuple, out object value) { + long itemCount = Runtime.PyTuple_Size(tuple.Handle); + if (itemCount == 0) { + value = EmptyTuple; + return true; + } + var elements = new object[itemCount]; + var itemTypes = new Type[itemCount]; + value = null; + for (int itemIndex = 0; itemIndex < elements.Length; itemIndex++) { + var pyItem = Runtime.PyTuple_GetItem(tuple.Handle, itemIndex); + if (!Converter.ToManaged(pyItem, typeof(object), out elements[itemIndex], setError: false)) { + return false; + } + + itemTypes[itemIndex] = elements[itemIndex]?.GetType() ?? typeof(object); + } + + var factory = tupleCreate[itemCount].MakeGenericMethod(itemTypes); + value = factory.Invoke(null, elements); + return true; + } + + static readonly MethodInfo[] tupleCreate = + typeof(TTuple).GetMethods(BindingFlags.Public | BindingFlags.Static) + .Where(m => m.Name == nameof(Tuple.Create)) + .OrderBy(m => m.GetParameters().Length) + .ToArray(); + + static readonly object EmptyTuple = tupleCreate[0].Invoke(null, parameters: new object[0]); + + public static void Register() { + PyObjectConversions.RegisterEncoder(Instance); + PyObjectConversions.RegisterDecoder(Instance); + } + } +} diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 74c70c490..1fb7360ac 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -145,7 +145,15 @@ internal static IntPtr ToPython(object value, Type type) return result; } - if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType) + if (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object)) { + var encoded = PyObjectConversions.TryEncode(value, type); + if (encoded != null) { + Runtime.XIncref(encoded.Handle); + return encoded.Handle; + } + } + + if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType) { using (var resultlist = new PyList()) { @@ -448,6 +456,12 @@ internal static bool ToManagedValue(IntPtr value, Type obType, { return true; } + + IntPtr pyType = Runtime.PyObject_TYPE(value); + if (PyObjectConversions.TryDecode(value, pyType, obType, out result)) + { + return true; + } } if (obType.IsEnum) @@ -476,17 +490,18 @@ static TryConvertFromPythonDelegate GetConverter(Type targetType) convert = convert.MakeGenericMethod(targetType); bool TryConvert(IntPtr pyHandle, out object result) { - var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle)); - var @params = new object[] { pyObj, null }; - bool success = (bool)convert.Invoke(converterAttribute, @params); - result = @params[1]; - return success; + using (var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle))) { + var @params = new object[] {pyObj, null}; + bool success = (bool)convert.Invoke(converterAttribute, @params); + result = @params[1]; + return success; + } } return TryConvert; } - delegate bool TryConvertFromPythonDelegate(IntPtr pyObj, out object result); + internal delegate bool TryConvertFromPythonDelegate(IntPtr pyObj, out object result); static readonly ConcurrentDictionary TypeConverterCache = new ConcurrentDictionary(); diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs new file mode 100644 index 000000000..6fe5ff484 --- /dev/null +++ b/src/runtime/converterextensions.cs @@ -0,0 +1,163 @@ +namespace Python.Runtime { + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + + /// + /// Defines conversion to CLR types (unmarshalling) + /// + public interface IPyObjectDecoder { + /// + /// Checks if this decoder can decode from to + /// + bool CanDecode(PyObject objectType, Type targetType); + /// + /// Attempts do decode into a variable of specified type + /// + /// CLR type to decode into + /// Object to decode + /// The variable, that will receive decoding result + /// + bool TryDecode(PyObject pyObj, out T value); + } + + /// + /// Defines conversion from CLR objects into Python objects (e.g. ) (marshalling) + /// + public interface IPyObjectEncoder { + /// + /// Checks if encoder can encode CLR objects of specified type + /// + bool CanEncode(Type type); + /// + /// Attempts to encode CLR object into Python object + /// + PyObject TryEncode(object value); + } + + /// + /// This class allows to register additional marshalling codecs. + /// Python.NET will pick suitable encoder/decoder registered first + /// + public static class PyObjectConversions { + static readonly List decoders = new List(); + static readonly List encoders = new List(); + + /// + /// Registers specified encoder (marshaller) + /// Python.NET will pick suitable encoder/decoder registered first + /// + public static void RegisterEncoder(IPyObjectEncoder encoder) { + if (encoder == null) throw new ArgumentNullException(nameof(encoder)); + + lock (encoders) { + encoders.Add(encoder); + } + } + + /// + /// Registers specified decoder (unmarshaller) + /// Python.NET will pick suitable encoder/decoder registered first + /// + public static void RegisterDecoder(IPyObjectDecoder decoder) { + if (decoder == null) throw new ArgumentNullException(nameof(decoder)); + + lock (decoders) { + decoders.Add(decoder); + } + } + + #region Encoding + internal static PyObject TryEncode(object obj, Type type) { + if (obj == null) throw new ArgumentNullException(nameof(obj)); + if (type == null) throw new ArgumentNullException(nameof(type)); + + foreach (var encoder in clrToPython.GetOrAdd(type, GetEncoders)) { + var result = encoder.TryEncode(obj); + if (result != null) return result; + } + + return null; + } + + static readonly ConcurrentDictionary + clrToPython = new ConcurrentDictionary(); + static IPyObjectEncoder[] GetEncoders(Type type) { + lock (encoders) { + return encoders.Where(encoder => encoder.CanEncode(type)).ToArray(); + } + } + #endregion + + #region Decoding + static readonly ConcurrentDictionary + pythonToClr = new ConcurrentDictionary(); + internal static bool TryDecode(IntPtr pyHandle, IntPtr pyType, Type targetType, out object result) { + if (pyHandle == IntPtr.Zero) throw new ArgumentNullException(nameof(pyHandle)); + if (pyType == IntPtr.Zero) throw new ArgumentNullException(nameof(pyType)); + if (targetType == null) throw new ArgumentNullException(nameof(targetType)); + + var decoder = pythonToClr.GetOrAdd(new TypePair(pyType, targetType), pair => GetDecoder(pair.PyType, pair.ClrType)); + result = null; + if (decoder == null) return false; + return decoder.Invoke(pyHandle, out result); + } + + static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type targetType) { + IPyObjectDecoder decoder; + using (var pyType = new PyObject(sourceType)) { + lock (decoders) { + decoder = decoders.Find(d => d.CanDecode(pyType, targetType)); + if (decoder == null) return null; + } + } + + var decode = genericDecode.MakeGenericMethod(targetType); + + bool TryDecode(IntPtr pyHandle, out object result) { + using (var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle))) { + var @params = new object[] { pyObj, null }; + bool success = (bool)decode.Invoke(decoder, @params); + result = @params[1]; + return success; + } + } + + return TryDecode; + } + + static readonly MethodInfo genericDecode = typeof(IPyObjectDecoder).GetMethod(nameof(IPyObjectDecoder.TryDecode)); + + #endregion + + internal static void Reset() { + lock (encoders) + lock (decoders) { + clrToPython.Clear(); + pythonToClr.Clear(); + encoders.Clear(); + decoders.Clear(); + } + } + + struct TypePair : IEquatable { + internal readonly IntPtr PyType; + internal readonly Type ClrType; + + public TypePair(IntPtr pyType, Type clrType) { + this.PyType = pyType; + this.ClrType = clrType; + } + + public override int GetHashCode() + => this.ClrType.GetHashCode() ^ this.PyType.GetHashCode(); + + public bool Equals(TypePair other) + => this.PyType == other.PyType && this.ClrType == other.ClrType; + + public override bool Equals(object obj) => obj is TypePair other && this.Equals(other); + } + } +} diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index f44359af5..b0d71c112 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -306,6 +306,8 @@ public static void Shutdown() ExecuteShutdownHandlers(); + PyObjectConversions.Reset(); + initialized = false; } } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 08bce609f..3ce3eaa1a 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -350,6 +350,7 @@ internal static void Initialize(bool initSigs = false) PyTrue = PyObject_GetAttrString(op, "True"); PyFalse = PyObject_GetAttrString(op, "False"); PySuper = PyObject_GetAttrString(op, "super"); + PyTuple = PyObject_GetAttrString(op, "tuple"); PyBoolType = PyObject_Type(PyTrue); PyNoneType = PyObject_Type(PyNone); @@ -549,6 +550,7 @@ internal static int AtExit() internal static IntPtr PyNone; internal static IntPtr Error; internal static IntPtr PySuper; + internal static IntPtr PyTuple; private static readonly Lazy inspect = new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); From 7c7d7373b171c2122396d1700be8731fbab02365 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 11 Sep 2019 22:26:35 -0700 Subject: [PATCH 077/240] fixed inherited Python __call__ method not making .NET object callable after the recent inheritance change --- src/runtime/classobject.cs | 68 ++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index a73daf177..02acdc478 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; @@ -300,43 +301,39 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) IntPtr methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) { - Runtime.XDecrefIgnoreNull(methodObjectHandle); Exceptions.SetError(Exceptions.TypeError, "object is not callable"); return IntPtr.Zero; } - try + if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) { - if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) - { - return methodObject.Invoke(ob, args, kw); - } + return methodObject.Invoke(ob, args, kw); + } - IntPtr pythonBase = GetPythonBase(tp); + methodObjectHandle = IntPtr.Zero; + + foreach (IntPtr pythonBase in GetPythonBases(tp)) { dict = Marshal.ReadIntPtr(pythonBase, TypeOffset.tp_dict); - Runtime.XDecref(methodObjectHandle); + methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); - if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) - { - Exceptions.SetError(Exceptions.TypeError, "object is not callable"); - return IntPtr.Zero; - } + if (methodObjectHandle != IntPtr.Zero && methodObjectHandle != Runtime.PyNone) break; + } + + if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) { + Exceptions.SetError(Exceptions.TypeError, "object is not callable"); + return IntPtr.Zero; + } - var boundMethod = Runtime.PyMethod_New(methodObjectHandle, ob); - if (boundMethod == IntPtr.Zero) { return IntPtr.Zero; } + var boundMethod = Runtime.PyMethod_New(methodObjectHandle, ob); + if (boundMethod == IntPtr.Zero) { return IntPtr.Zero; } - try - { - return Runtime.PyObject_Call(boundMethod, args, kw); - } - finally - { - Runtime.XDecref(boundMethod); - } + try + { + return Runtime.PyObject_Call(boundMethod, args, kw); } finally { - Runtime.XDecrefIgnoreNull(methodObjectHandle); + Runtime.XDecref(boundMethod); } } @@ -353,16 +350,31 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) } /// - /// Get the first base class in the class hierarchy - /// of the specified .NET type, that is defined in Python. + /// Enumerate Python base types of the specified .NET type in mro order. /// - internal static IntPtr GetPythonBase(IntPtr tp) { + internal static IEnumerable GetPythonBases(IntPtr tp) { Debug.Assert(IsManagedType(tp)); do { + IntPtr bases = Marshal.ReadIntPtr(tp, TypeOffset.tp_bases); + if (bases != IntPtr.Zero) { + long baseCount = Runtime.PyTuple_Size(bases); + for (long baseIndex = 0; baseIndex < baseCount; baseIndex++) { + IntPtr @base = Runtime.PyTuple_GetItem(bases, baseIndex); + if (IsManagedType(@base)) { + foreach (IntPtr innerBase in GetPythonBases(@base)) { + yield return innerBase; + } + } else { + yield return @base; + } + } + yield break; + } + tp = Marshal.ReadIntPtr(tp, TypeOffset.tp_base); } while (IsManagedType(tp)); - return tp; + yield return tp; } internal static bool IsManagedType(IntPtr tp) From f8040c90ffd8c520202d316f00d8c1d749a957d0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 22 Sep 2019 23:06:35 -0700 Subject: [PATCH 078/240] enable BaseTypeAttributeBase to set multiple bases --- src/embed_tests/CallableObject.cs | 7 ++- src/embed_tests/Inheritance.cs | 25 +++++++++-- src/runtime/BaseTypeAttributeBase.cs | 19 +++++++-- src/runtime/pytuple.cs | 3 ++ src/runtime/pytype.cs | 64 ++++++++++++++++++++++++++++ src/runtime/typemanager.cs | 58 ++++++++++--------------- 6 files changed, 133 insertions(+), 43 deletions(-) create mode 100644 src/runtime/pytype.cs diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index c1d358faf..395215c90 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -57,8 +57,11 @@ def __call__(self, val): class CustomBaseTypeAttribute : BaseTypeAttributeBase { internal static PyObject BaseClass; - public override IntPtr BaseType(Type type) - => type != typeof(CallViaInheritance) ? IntPtr.Zero : BaseClass.Handle; + public override PyTuple BaseTypes(Type type) { + return type != typeof(CallViaInheritance) + ? base.BaseTypes(type) + : PyTuple.FromSingleElement(BaseClass.Handle); + } } } } diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index d721e9571..83342247d 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -78,18 +78,31 @@ public void CanCallInheritedMethodWithPythonBase() { Assert.AreEqual(result, nameof(PythonWrapperBase.WrapperBaseMethod)); } } + + [Test] + public void PythonCanCallOverridenMethod() { + var instance = new Inherited(); + using (Py.GIL()) + using (var scope = Py.CreateScope()){ + scope.Set(nameof(instance), instance); + int actual = scope.Eval($"{nameof(instance)}.callVirt()"); + Assert.AreEqual(expected: Inherited.OverridenVirtValue, actual); + } + } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] class CustomBaseTypeAttribute : BaseTypeAttributeBase { internal static PyObject BaseClass; - public override IntPtr BaseType(Type type) - => type != typeof(InheritanceTestBaseClassWrapper) ? IntPtr.Zero : BaseClass.Handle; + public override PyTuple BaseTypes(Type type) + => type != typeof(InheritanceTestBaseClassWrapper) + ? base.BaseTypes(type) + : new PyTuple(new []{ PyType.Get(type.BaseType), BaseClass }); } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] class DefaultBaseTypeAttribute : BaseTypeAttributeBase { - public override IntPtr BaseType(Type type) => IntPtr.Zero; + } [DefaultBaseType] @@ -102,6 +115,10 @@ public class InheritanceTestBaseClassWrapper : PythonWrapperBase { public const string ClassName = "InheritanceTestBaseClass"; public const string ClassSourceCode = "class " + ClassName + @": + def virt(self): + return 42 + def callVirt(self): + return self.virt() def __getattr__(self, name): return '__getattr__:' + name def __setattr__(self, name, value): @@ -110,5 +127,7 @@ def __setattr__(self, name, value): } public class Inherited : InheritanceTestBaseClassWrapper { + public const int OverridenVirtValue = -42; + public int virt() => OverridenVirtValue; } } diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs index 58d9255b1..b8be479ea 100644 --- a/src/runtime/BaseTypeAttributeBase.cs +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -9,12 +9,25 @@ namespace Python.Runtime | AttributeTargets.Interface | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] - public abstract class BaseTypeAttributeBase : Attribute + public class BaseTypeAttributeBase : Attribute { /// - /// Get the handle of a Python type, that should be presented to Python as the base type + /// Get a tuple of Python type(s), that should be presented to Python as the base type(s) /// for the specified .NET type. /// - public abstract IntPtr BaseType(Type type); + public virtual PyTuple BaseTypes(Type type) { + if (type == null) throw new ArgumentNullException(nameof(type)); + if (type == typeof(Exception)) + { + return PyTuple.FromSingleElement(Exceptions.Exception); + } + + if (type.BaseType != null) { + ClassBase bc = ClassManager.GetClass(type.BaseType); + return PyTuple.FromSingleElement(bc.pyHandle); + } + + return null; + } } } diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 45f3d8350..e20662b8b 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -104,5 +104,8 @@ public static PyTuple AsTuple(PyObject value) Runtime.CheckExceptionOccurred(); return new PyTuple(op); } + + internal static PyTuple FromSingleElement(IntPtr value) + => new PyTuple(items: new []{new PyObject(value)}); } } diff --git a/src/runtime/pytype.cs b/src/runtime/pytype.cs new file mode 100644 index 000000000..9e4749a6f --- /dev/null +++ b/src/runtime/pytype.cs @@ -0,0 +1,64 @@ +namespace Python.Runtime { + using System; + + public class PyType : PyObject + { + /// + /// Creates a new instance from an existing object reference. Note + /// that the instance assumes ownership of the object reference. + /// The object reference is not checked for type-correctness. + /// + public PyType(IntPtr ptr) : base(ptr) { } + + /// + /// Creates a new instance from an existing object reference. + /// Ensures the type of the object is Python type. + /// + public PyType(PyObject o) { + if (o == null) { + throw new ArgumentNullException(nameof(o)); + } + + if (!IsTypeType(o)) { + throw new ArgumentException("object is not a type"); + } + Runtime.XIncref(o.obj); + this.obj = o.obj; + } + + /// + /// Returns true if the given object is Python type. + /// + public static bool IsTypeType(PyObject obj) { + if (obj == null) { + throw new ArgumentNullException(nameof(obj)); + } + + return Runtime.PyType_Check(obj.Handle); + } + + /// + /// Returns true if the given object is Python type. + /// + public static bool IsTypeType(IntPtr typeHandle) { + if (typeHandle == IntPtr.Zero) { + throw new ArgumentNullException(nameof(typeHandle)); + } + + return Runtime.PyType_Check(typeHandle); + } + + /// + /// Gets , which represents the specified CLR type. + /// Must be called after the CLR type was mapped to its Python type. + /// + public static PyType Get(Type clrType) { + if (clrType == null) { + throw new ArgumentNullException(nameof(clrType)); + } + + ClassBase pyClass = ClassManager.GetClass(clrType); + return new PyType(Runtime.SelfIncRef(pyClass.pyHandle)); + } + } +} diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 14c170eaf..f04901583 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -136,17 +136,25 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); } - IntPtr base_ = GetBaseType(clrType, out IntPtr bases); - if (base_ != IntPtr.Zero) + try { - Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); - Runtime.XIncref(base_); + IntPtr base_ = GetBaseType(clrType, out IntPtr bases); + if (base_ != IntPtr.Zero) + { + Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); + Runtime.XIncref(base_); - if (bases != IntPtr.Zero) { - Marshal.WriteIntPtr(type, TypeOffset.tp_bases, bases); - Runtime.XIncref(bases); + if (bases != IntPtr.Zero) { + Marshal.WriteIntPtr(type, TypeOffset.tp_bases, bases); + Runtime.XIncref(bases); + } } } + catch (Exception error) + { + Exceptions.SetError(error); + return IntPtr.Zero; + } int flags = TypeFlags.Default; flags |= TypeFlags.Managed; @@ -246,37 +254,17 @@ static IntPtr GetBaseType(Type clrType, out IntPtr baseTypes) return Exceptions.Exception; } - var bases = new List(); - - // .NET base class must always come first - if (clrType.BaseType != null) - { - ClassBase bc = ClassManager.GetClass(clrType.BaseType); - bases.Add(bc.pyHandle); - } - var baseOverride = Util.GetLatestAttribute(clrType); - IntPtr handle = baseOverride?.BaseType(clrType) ?? IntPtr.Zero; - if (handle != IntPtr.Zero) { - if ((Util.ReadCLong(handle, TypeOffset.tp_flags) & TypeFlags.BaseType) == 0) { - throw new InvalidProgramException("The specified base Python type can not be inherited from"); - } - - bases.Add(handle); - } - - switch (bases.Count) { - case 0: - return IntPtr.Zero; - case 1: - return bases[0]; - default: - baseTypes = Runtime.PyTuple_New(bases.Count); - for (int baseIndex = 0; baseIndex < bases.Count; baseIndex++) { - Runtime.PyTuple_SetItem(baseTypes, baseIndex, bases[baseIndex]); + var types = baseOverride?.BaseTypes(clrType); + if (types == null || types.Length() == 0) return IntPtr.Zero; + for (int index = 0; index < types.Length(); index++) { + IntPtr baseType = Runtime.PyTuple_GetItem(types.Handle, index); + if (!PyType.IsTypeType(baseType)) { + throw new InvalidOperationException("Entries in base types must be Python types themselves"); } - return bases[0]; } + baseTypes = types.Handle; + return types[0].Handle; } internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) From 8dc6115f110e5852a2fb94920429d91b053280de Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 24 Sep 2019 12:29:37 -0700 Subject: [PATCH 079/240] added parameter validation to PyObject methods --- src/embed_tests/TestPyObject.cs | 6 ++ src/runtime/pyobject.cs | 108 ++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/TestPyObject.cs b/src/embed_tests/TestPyObject.cs index 65ac20e9a..d4952d4a3 100644 --- a/src/embed_tests/TestPyObject.cs +++ b/src/embed_tests/TestPyObject.cs @@ -57,5 +57,11 @@ def add(self, x, y): Assert.IsTrue(memberNames.Contains(expectedName), "Could not find member '{0}'.", expectedName); } } + + [Test] + public void InvokeNull() { + var list = PythonEngine.Eval("list"); + Assert.Throws(() => list.Invoke(new PyObject[] {null})); + } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index ba58d362b..a0e674df5 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Dynamic; +using System.Linq; using System.Linq.Expressions; namespace Python.Runtime @@ -29,12 +30,14 @@ public class PyObject : DynamicObject, IEnumerable, IDisposable /// public PyObject(IntPtr ptr) { + if (ptr == IntPtr.Zero) throw new ArgumentNullException(nameof(ptr)); + obj = ptr; } // Protected default constructor to allow subclasses to manage // initialization in different ways as appropriate. - + [Obsolete("Please, always use PyObject(IntPtr)")] protected PyObject() { } @@ -181,6 +184,8 @@ public PyObject GetPythonType() /// public bool TypeCheck(PyObject typeOrClass) { + if (typeOrClass == null) throw new ArgumentNullException(nameof(typeOrClass)); + return Runtime.PyObject_TypeCheck(obj, typeOrClass.obj); } @@ -193,6 +198,8 @@ public bool TypeCheck(PyObject typeOrClass) /// public bool HasAttr(string name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + return Runtime.PyObject_HasAttrString(obj, name) != 0; } @@ -206,6 +213,8 @@ public bool HasAttr(string name) /// public bool HasAttr(PyObject name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + return Runtime.PyObject_HasAttr(obj, name.obj) != 0; } @@ -219,6 +228,8 @@ public bool HasAttr(PyObject name) /// public PyObject GetAttr(string name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); Exceptions.ErrorCheck(op); return new PyObject(op); @@ -226,14 +237,17 @@ public PyObject GetAttr(string name) /// - /// GetAttr Method + /// GetAttr Method. Returns fallback value if getting attribute fails for any reason. /// /// /// Returns the named attribute of the Python object, or the given /// default object if the attribute access fails. /// + [Obsolete("This method ignores any Python exceptions, and should not be used. Use GetAttrOrElse.")] public PyObject GetAttr(string name, PyObject _default) { + if (name == null) throw new ArgumentNullException(nameof(name)); + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); if (op == IntPtr.Zero) { @@ -243,6 +257,27 @@ public PyObject GetAttr(string name, PyObject _default) return new PyObject(op); } + /// + /// Gets the specified attribute. If attribute is not found, returns the fallback value. + /// + public PyObject GetAttrOrElse(string name, PyObject _default) + { + if (name == null) throw new ArgumentNullException(nameof(name)); + + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); + if (op == IntPtr.Zero) + { + if (!Exceptions.ExceptionMatches(Exceptions.AttributeError)) + { + throw PythonException.FromPyErr(); + } + + Runtime.PyErr_Clear(); + return _default; + } + return new PyObject(op); + } + /// /// GetAttr Method @@ -254,6 +289,8 @@ public PyObject GetAttr(string name, PyObject _default) /// public PyObject GetAttr(PyObject name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj); Exceptions.ErrorCheck(op); return new PyObject(op); @@ -270,6 +307,8 @@ public PyObject GetAttr(PyObject name) /// public PyObject GetAttr(PyObject name, PyObject _default) { + if (name == null) throw new ArgumentNullException(nameof(name)); + IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj); if (op == IntPtr.Zero) { @@ -289,6 +328,9 @@ public PyObject GetAttr(PyObject name, PyObject _default) /// public void SetAttr(string name, PyObject value) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (value == null) throw new ArgumentNullException(nameof(value)); + int r = Runtime.PyObject_SetAttrString(obj, name, value.obj); if (r < 0) { @@ -307,6 +349,9 @@ public void SetAttr(string name, PyObject value) /// public void SetAttr(PyObject name, PyObject value) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (value == null) throw new ArgumentNullException(nameof(value)); + int r = Runtime.PyObject_SetAttr(obj, name.obj, value.obj); if (r < 0) { @@ -324,6 +369,8 @@ public void SetAttr(PyObject name, PyObject value) /// public void DelAttr(string name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + int r = Runtime.PyObject_SetAttrString(obj, name, IntPtr.Zero); if (r < 0) { @@ -342,6 +389,8 @@ public void DelAttr(string name) /// public void DelAttr(PyObject name) { + if (name == null) throw new ArgumentNullException(nameof(name)); + int r = Runtime.PyObject_SetAttr(obj, name.obj, IntPtr.Zero); if (r < 0) { @@ -360,6 +409,8 @@ public void DelAttr(PyObject name) /// public virtual PyObject GetItem(PyObject key) { + if (key == null) throw new ArgumentNullException(nameof(key)); + IntPtr op = Runtime.PyObject_GetItem(obj, key.obj); if (op == IntPtr.Zero) { @@ -379,6 +430,8 @@ public virtual PyObject GetItem(PyObject key) /// public virtual PyObject GetItem(string key) { + if (key == null) throw new ArgumentNullException(nameof(key)); + using (var pyKey = new PyString(key)) { return GetItem(pyKey); @@ -413,6 +466,9 @@ public virtual PyObject GetItem(int index) /// public virtual void SetItem(PyObject key, PyObject value) { + if (key == null) throw new ArgumentNullException(nameof(key)); + if (value == null) throw new ArgumentNullException(nameof(value)); + int r = Runtime.PyObject_SetItem(obj, key.obj, value.obj); if (r < 0) { @@ -431,6 +487,9 @@ public virtual void SetItem(PyObject key, PyObject value) /// public virtual void SetItem(string key, PyObject value) { + if (key == null) throw new ArgumentNullException(nameof(key)); + if (value == null) throw new ArgumentNullException(nameof(value)); + using (var pyKey = new PyString(key)) { SetItem(pyKey, value); @@ -448,6 +507,8 @@ public virtual void SetItem(string key, PyObject value) /// public virtual void SetItem(int index, PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + using (var pyindex = new PyInt(index)) { SetItem(pyindex, value); @@ -465,6 +526,8 @@ public virtual void SetItem(int index, PyObject value) /// public virtual void DelItem(PyObject key) { + if (key == null) throw new ArgumentNullException(nameof(key)); + int r = Runtime.PyObject_DelItem(obj, key.obj); if (r < 0) { @@ -483,6 +546,8 @@ public virtual void DelItem(PyObject key) /// public virtual void DelItem(string key) { + if (key == null) throw new ArgumentNullException(nameof(key)); + using (var pyKey = new PyString(key)) { DelItem(pyKey); @@ -606,6 +671,9 @@ public IEnumerator GetEnumerator() /// public PyObject Invoke(params PyObject[] args) { + if (args == null) throw new ArgumentNullException(nameof(args)); + if (args.Contains(null)) throw new ArgumentNullException(); + var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, IntPtr.Zero); t.Dispose(); @@ -623,6 +691,8 @@ public PyObject Invoke(params PyObject[] args) /// public PyObject Invoke(PyTuple args) { + if (args == null) throw new ArgumentNullException(nameof(args)); + IntPtr r = Runtime.PyObject_Call(obj, args.obj, IntPtr.Zero); Exceptions.ErrorCheck(r); return new PyObject(r); @@ -638,8 +708,11 @@ public PyObject Invoke(PyTuple args) /// public PyObject Invoke(PyObject[] args, PyDict kw) { + if (args == null) throw new ArgumentNullException(nameof(args)); + if (args.Contains(null)) throw new ArgumentNullException(); + var t = new PyTuple(args); - IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw != null ? kw.obj : IntPtr.Zero); + IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw?.obj ?? IntPtr.Zero); t.Dispose(); Exceptions.ErrorCheck(r); return new PyObject(r); @@ -655,7 +728,9 @@ public PyObject Invoke(PyObject[] args, PyDict kw) /// public PyObject Invoke(PyTuple args, PyDict kw) { - IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw != null ? kw.obj : IntPtr.Zero); + if (args == null) throw new ArgumentNullException(nameof(args)); + + IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw?.obj ?? IntPtr.Zero); Exceptions.ErrorCheck(r); return new PyObject(r); } @@ -670,6 +745,10 @@ public PyObject Invoke(PyTuple args, PyDict kw) /// public PyObject InvokeMethod(string name, params PyObject[] args) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + if (args.Contains(null)) throw new ArgumentNullException(); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args); method.Dispose(); @@ -686,6 +765,9 @@ public PyObject InvokeMethod(string name, params PyObject[] args) /// public PyObject InvokeMethod(string name, PyTuple args) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args); method.Dispose(); @@ -701,6 +783,10 @@ public PyObject InvokeMethod(string name, PyTuple args) /// public PyObject InvokeMethod(PyObject name, params PyObject[] args) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + if (args.Contains(null)) throw new ArgumentNullException(); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args); method.Dispose(); @@ -717,6 +803,9 @@ public PyObject InvokeMethod(PyObject name, params PyObject[] args) /// public PyObject InvokeMethod(PyObject name, PyTuple args) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args); method.Dispose(); @@ -734,6 +823,10 @@ public PyObject InvokeMethod(PyObject name, PyTuple args) /// public PyObject InvokeMethod(string name, PyObject[] args, PyDict kw) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + if (args.Contains(null)) throw new ArgumentNullException(); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args, kw); method.Dispose(); @@ -751,6 +844,9 @@ public PyObject InvokeMethod(string name, PyObject[] args, PyDict kw) /// public PyObject InvokeMethod(string name, PyTuple args, PyDict kw) { + if (name == null) throw new ArgumentNullException(nameof(name)); + if (args == null) throw new ArgumentNullException(nameof(args)); + PyObject method = GetAttr(name); PyObject result = method.Invoke(args, kw); method.Dispose(); @@ -767,6 +863,8 @@ public PyObject InvokeMethod(string name, PyTuple args, PyDict kw) /// public bool IsInstance(PyObject typeOrClass) { + if (typeOrClass == null) throw new ArgumentNullException(nameof(typeOrClass)); + int r = Runtime.PyObject_IsInstance(obj, typeOrClass.obj); if (r < 0) { @@ -786,6 +884,8 @@ public bool IsInstance(PyObject typeOrClass) /// public bool IsSubclass(PyObject typeOrClass) { + if (typeOrClass == null) throw new ArgumentNullException(nameof(typeOrClass)); + int r = Runtime.PyObject_IsSubclass(obj, typeOrClass.obj); if (r < 0) { From 4aa1f94faf83f64a32ae244277a43b659732df93 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 24 Sep 2019 12:58:08 -0700 Subject: [PATCH 080/240] Exceptions.ErrorCheck* returns its argument on success --- src/runtime/exceptions.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 5093a1fd8..76d1e0b5f 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -168,23 +168,27 @@ 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 IntPtr ErrorCheck(IntPtr pointer) { if (pointer == IntPtr.Zero) { throw PythonException.FromPyErr(); } + + return pointer; } /// /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException /// - internal static void ErrorOccurredCheck(IntPtr pointer) + internal static IntPtr ErrorOccurredCheck(IntPtr pointer) { if (pointer == IntPtr.Zero || ErrorOccurred()) { throw PythonException.FromPyErr(); } + + return pointer; } /// From bd76771d301eecb0486cad81d69d432dcdd46c16 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 24 Sep 2019 13:07:38 -0700 Subject: [PATCH 081/240] more parameter validation --- src/runtime/pyansistring.cs | 16 +++++++++---- src/runtime/pydict.cs | 17 +++++++------- src/runtime/pyfloat.cs | 26 ++++++++++++++------ src/runtime/pyint.cs | 36 ++++++++++++++-------------- src/runtime/pysequence.cs | 1 + src/runtime/pystring.cs | 20 ++++++++++------ src/runtime/pytuple.cs | 47 +++++++++++++++++++++++++------------ src/runtime/pytype.cs | 10 ++++---- 8 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs index 3d1d6ab68..a9cae0a8a 100644 --- a/src/runtime/pyansistring.cs +++ b/src/runtime/pyansistring.cs @@ -25,14 +25,20 @@ public PyAnsiString(IntPtr ptr) : base(ptr) /// An ArgumentException will be thrown if the given object is not /// a Python string object. /// - public PyAnsiString(PyObject o) + public PyAnsiString(PyObject o): base(FromPyObject(o)) { + } + + static IntPtr FromPyObject(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); + if (!IsStringType(o)) { throw new ArgumentException("object is not a string"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } @@ -42,10 +48,8 @@ public PyAnsiString(PyObject o) /// /// Creates a Python string from a managed string. /// - public PyAnsiString(string s) + public PyAnsiString(string s):base(Exceptions.ErrorOccurredCheck(Runtime.PyString_FromString(s))) { - obj = Runtime.PyString_FromString(s); - Runtime.CheckExceptionOccurred(); } @@ -57,6 +61,8 @@ public PyAnsiString(string s) /// public static bool IsStringType(PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + return Runtime.PyString_Check(value.obj); } } diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs index 4949f08fc..7ea5b8cb0 100644 --- a/src/runtime/pydict.cs +++ b/src/runtime/pydict.cs @@ -29,13 +29,8 @@ public PyDict(IntPtr ptr) : base(ptr) /// /// Creates a new Python dictionary object. /// - public PyDict() + public PyDict():base(Exceptions.ErrorCheck(Runtime.PyDict_New())) { - obj = Runtime.PyDict_New(); - if (obj == IntPtr.Zero) - { - throw PythonException.FromPyErr(); - } } @@ -47,14 +42,20 @@ public PyDict() /// ArgumentException will be thrown if the given object is not a /// Python dictionary object. /// - public PyDict(PyObject o) + public PyDict(PyObject o):base(FromPyObject(o)) { + } + + static IntPtr FromPyObject(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); + if (!IsDictType(o)) { throw new ArgumentException("object is not a dict"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs index edfaca542..d584feb7d 100644 --- a/src/runtime/pyfloat.cs +++ b/src/runtime/pyfloat.cs @@ -31,14 +31,19 @@ public PyFloat(IntPtr ptr) : base(ptr) /// ArgumentException will be thrown if the given object is not a /// Python float object. /// - public PyFloat(PyObject o) + public PyFloat(PyObject o):base(FromPyObject(o)) { + } + + static IntPtr FromPyObject(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); if (!IsFloatType(o)) { throw new ArgumentException("object is not a float"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } @@ -48,10 +53,8 @@ public PyFloat(PyObject o) /// /// Creates a new Python float from a double value. /// - public PyFloat(double value) + public PyFloat(double value):base(Exceptions.ErrorOccurredCheck(Runtime.PyFloat_FromDouble(value))) { - obj = Runtime.PyFloat_FromDouble(value); - Runtime.CheckExceptionOccurred(); } @@ -61,12 +64,19 @@ public PyFloat(double value) /// /// Creates a new Python float from a string value. /// - public PyFloat(string value) + public PyFloat(string value):base(FromString(value)) { + } + + static IntPtr FromString(string value) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + using (var s = new PyString(value)) { - obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero); + var obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero); Runtime.CheckExceptionOccurred(); + return obj; } } @@ -79,6 +89,8 @@ public PyFloat(string value) /// public static bool IsFloatType(PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + return Runtime.PyFloat_Check(value.obj); } diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs index f6911d9d7..f367d922e 100644 --- a/src/runtime/pyint.cs +++ b/src/runtime/pyint.cs @@ -31,14 +31,20 @@ public PyInt(IntPtr ptr) : base(ptr) /// ArgumentException will be thrown if the given object is not a /// Python int object. /// - public PyInt(PyObject o) + public PyInt(PyObject o):base(FromPyObject(o)) { + } + + static IntPtr FromPyObject(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); + if (!IsIntType(o)) { throw new ArgumentException("object is not an int"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } @@ -48,10 +54,8 @@ public PyInt(PyObject o) /// /// Creates a new Python int from an int32 value. /// - public PyInt(int value) + public PyInt(int value):base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt32(value))) { - obj = Runtime.PyInt_FromInt32(value); - Runtime.CheckExceptionOccurred(); } @@ -62,10 +66,8 @@ public PyInt(int value) /// Creates a new Python int from a uint32 value. /// [CLSCompliant(false)] - public PyInt(uint value) : base(IntPtr.Zero) + public PyInt(uint value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64(value))) { - obj = Runtime.PyInt_FromInt64(value); - Runtime.CheckExceptionOccurred(); } @@ -75,10 +77,8 @@ public PyInt(uint value) : base(IntPtr.Zero) /// /// Creates a new Python int from an int64 value. /// - public PyInt(long value) : base(IntPtr.Zero) + public PyInt(long value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64(value))) { - obj = Runtime.PyInt_FromInt64(value); - Runtime.CheckExceptionOccurred(); } @@ -89,10 +89,8 @@ public PyInt(long value) : base(IntPtr.Zero) /// Creates a new Python int from a uint64 value. /// [CLSCompliant(false)] - public PyInt(ulong value) : base(IntPtr.Zero) + public PyInt(ulong value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64((long)value))) { - obj = Runtime.PyInt_FromInt64((long)value); - Runtime.CheckExceptionOccurred(); } @@ -148,10 +146,10 @@ public PyInt(sbyte value) : this((int)value) /// /// Creates a new Python int from a string value. /// - public PyInt(string value) + public PyInt(string value):base( + Exceptions.ErrorOccurredCheck( + Runtime.PyInt_FromString(value ?? throw new ArgumentNullException(nameof(value)), IntPtr.Zero, 0))) { - obj = Runtime.PyInt_FromString(value, IntPtr.Zero, 0); - Runtime.CheckExceptionOccurred(); } @@ -163,6 +161,8 @@ public PyInt(string value) /// public static bool IsIntType(PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + return Runtime.PyInt_Check(value.obj); } @@ -177,6 +177,8 @@ public static bool IsIntType(PyObject value) /// public static PyInt AsInt(PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + IntPtr op = Runtime.PyNumber_Int(value.obj); Runtime.CheckExceptionOccurred(); return new PyInt(op); diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs index 6899fb8cf..e2746aa29 100644 --- a/src/runtime/pysequence.cs +++ b/src/runtime/pysequence.cs @@ -16,6 +16,7 @@ protected PySequence(IntPtr ptr) : base(ptr) { } + [Obsolete] protected PySequence() { } diff --git a/src/runtime/pystring.cs b/src/runtime/pystring.cs index c9c4f9f5b..85b5af618 100644 --- a/src/runtime/pystring.cs +++ b/src/runtime/pystring.cs @@ -34,14 +34,19 @@ public PyString(IntPtr ptr) : base(ptr) /// An ArgumentException will be thrown if the given object is not /// a Python string object. /// - public PyString(PyObject o) + public PyString(PyObject o):base(FromString(o)) { + } + + static IntPtr FromString(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); if (!IsStringType(o)) { throw new ArgumentException("object is not a string"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } @@ -51,10 +56,10 @@ public PyString(PyObject o) /// /// Creates a Python string from a managed string. /// - public PyString(string s) + public PyString(string s):base( + Exceptions.ErrorOccurredCheck( + Runtime.PyUnicode_FromUnicode(s ?? throw new ArgumentNullException(nameof(s)), s.Length))) { - obj = Runtime.PyUnicode_FromUnicode(s, s.Length); - Runtime.CheckExceptionOccurred(); } @@ -64,8 +69,9 @@ public PyString(string s) /// /// Returns true if the given object is a Python string. /// - public static bool IsStringType(PyObject value) - { + public static bool IsStringType(PyObject value) { + if (value == null) throw new ArgumentNullException(nameof(value)); + return Runtime.PyString_Check(value.obj); } } diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index e20662b8b..2e583c689 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -31,14 +31,19 @@ public PyTuple(IntPtr ptr) : base(ptr) /// ArgumentException will be thrown if the given object is not a /// Python tuple object. /// - public PyTuple(PyObject o) + public PyTuple(PyObject o):base(FromPyObject(o)) { - if (!IsTupleType(o)) - { + } + + static IntPtr FromPyObject(PyObject o) + { + if (o == null) throw new ArgumentNullException(nameof(o)); + + if (!IsTupleType(o)) { throw new ArgumentException("object is not a tuple"); } Runtime.XIncref(o.obj); - obj = o.obj; + return o.obj; } @@ -48,10 +53,8 @@ public PyTuple(PyObject o) /// /// Creates a new empty PyTuple. /// - public PyTuple() + public PyTuple():base(Exceptions.ErrorOccurredCheck(Runtime.PyTuple_New(0))) { - obj = Runtime.PyTuple_New(0); - Runtime.CheckExceptionOccurred(); } @@ -64,17 +67,31 @@ public PyTuple() /// See caveats about PyTuple_SetItem: /// https://www.coursehero.com/file/p4j2ogg/important-exceptions-to-this-rule-PyTupleSetItem-and-PyListSetItem-These/ /// - public PyTuple(PyObject[] items) + public PyTuple(PyObject[] items):base(FromItems(items)) { + } + + static IntPtr FromItems(PyObject[] items) + { + if (items == null) throw new ArgumentNullException(nameof(items)); + int count = items.Length; - obj = Runtime.PyTuple_New(count); - for (var i = 0; i < count; i++) - { - IntPtr ptr = items[i].obj; - Runtime.XIncref(ptr); - Runtime.PyTuple_SetItem(obj, i, ptr); - Runtime.CheckExceptionOccurred(); + IntPtr obj = Runtime.PyTuple_New(count); + try { + for (var i = 0; i < count; i++) { + if (items[i] == null) throw new ArgumentNullException(); + + IntPtr ptr = items[i].obj; + Runtime.PyTuple_SetItem(obj, i, ptr); + Runtime.CheckExceptionOccurred(); + Runtime.XIncref(ptr); + } + } catch { + Runtime.XDecref(obj); + throw; } + + return obj; } diff --git a/src/runtime/pytype.cs b/src/runtime/pytype.cs index 9e4749a6f..1bf26e38a 100644 --- a/src/runtime/pytype.cs +++ b/src/runtime/pytype.cs @@ -14,16 +14,16 @@ public PyType(IntPtr ptr) : base(ptr) { } /// Creates a new instance from an existing object reference. /// Ensures the type of the object is Python type. /// - public PyType(PyObject o) { - if (o == null) { - throw new ArgumentNullException(nameof(o)); - } + public PyType(PyObject o) : base(FromPyObject(o)) { } + + static IntPtr FromPyObject(PyObject o) { + if (o == null) throw new ArgumentNullException(nameof(o)); if (!IsTypeType(o)) { throw new ArgumentException("object is not a type"); } Runtime.XIncref(o.obj); - this.obj = o.obj; + return o.obj; } /// From 31f14282c46de71b0880eb6b3a4b05c81de5d382 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 24 Sep 2019 13:11:49 -0700 Subject: [PATCH 082/240] disallow accessing handle of disposed PyObject --- src/runtime/pyobject.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index a0e674df5..b18b6d03e 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -62,10 +62,7 @@ protected PyObject() /// Gets the native handle of the underlying Python object. This /// value is generally for internal use by the PythonNet runtime. /// - public IntPtr Handle - { - get { return obj; } - } + public IntPtr Handle => obj == IntPtr.Zero ? throw new ObjectDisposedException(this.GetType().Name) : obj; /// From 8b8db530a9b5a07d58590892bbd9f8e461f19605 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 24 Sep 2019 14:38:07 -0700 Subject: [PATCH 083/240] debug builds will now assert GIL in many scenarios --- src/runtime/debughelper.cs | 8 ++++++ src/runtime/pyobject.cs | 53 ++++++++++++++++++++++++++++++++++++++ src/runtime/runtime.cs | 10 +++++++ 3 files changed, 71 insertions(+) diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index 287a140a8..26f62ef05 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -137,5 +137,13 @@ public static void PrintHexBytes(byte[] bytes) Console.WriteLine(); } } + + [Conditional("DEBUG")] + public static void EnsureGIL() + { + if (Runtime.PythonVersion >= new Version(3,4)) { + Debug.Assert(Runtime.PyGILState_Check() == 1, "GIL must be acquired"); + } + } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index b18b6d03e..24c33af47 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -227,6 +227,8 @@ public PyObject GetAttr(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); Exceptions.ErrorCheck(op); return new PyObject(op); @@ -245,6 +247,8 @@ public PyObject GetAttr(string name, PyObject _default) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); if (op == IntPtr.Zero) { @@ -261,6 +265,8 @@ public PyObject GetAttrOrElse(string name, PyObject _default) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetAttrString(obj, name); if (op == IntPtr.Zero) { @@ -288,6 +294,8 @@ public PyObject GetAttr(PyObject name) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj); Exceptions.ErrorCheck(op); return new PyObject(op); @@ -306,6 +314,8 @@ public PyObject GetAttr(PyObject name, PyObject _default) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj); if (op == IntPtr.Zero) { @@ -328,6 +338,8 @@ public void SetAttr(string name, PyObject value) if (name == null) throw new ArgumentNullException(nameof(name)); if (value == null) throw new ArgumentNullException(nameof(value)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_SetAttrString(obj, name, value.obj); if (r < 0) { @@ -349,6 +361,8 @@ public void SetAttr(PyObject name, PyObject value) if (name == null) throw new ArgumentNullException(nameof(name)); if (value == null) throw new ArgumentNullException(nameof(value)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_SetAttr(obj, name.obj, value.obj); if (r < 0) { @@ -368,6 +382,8 @@ public void DelAttr(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_SetAttrString(obj, name, IntPtr.Zero); if (r < 0) { @@ -388,6 +404,8 @@ public void DelAttr(PyObject name) { if (name == null) throw new ArgumentNullException(nameof(name)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_SetAttr(obj, name.obj, IntPtr.Zero); if (r < 0) { @@ -408,6 +426,8 @@ public virtual PyObject GetItem(PyObject key) { if (key == null) throw new ArgumentNullException(nameof(key)); + DebugUtil.EnsureGIL(); + IntPtr op = Runtime.PyObject_GetItem(obj, key.obj); if (op == IntPtr.Zero) { @@ -466,6 +486,8 @@ public virtual void SetItem(PyObject key, PyObject value) if (key == null) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_SetItem(obj, key.obj, value.obj); if (r < 0) { @@ -525,6 +547,8 @@ public virtual void DelItem(PyObject key) { if (key == null) throw new ArgumentNullException(nameof(key)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_DelItem(obj, key.obj); if (r < 0) { @@ -578,6 +602,8 @@ public virtual void DelItem(int index) /// public virtual long Length() { + DebugUtil.EnsureGIL(); + var s = Runtime.PyObject_Size(obj); if (s < 0) { @@ -640,6 +666,7 @@ public virtual PyObject this[int index] /// public PyObject GetIterator() { + DebugUtil.EnsureGIL(); IntPtr r = Runtime.PyObject_GetIter(obj); Exceptions.ErrorCheck(r); return new PyObject(r); @@ -671,6 +698,8 @@ public PyObject Invoke(params PyObject[] args) if (args == null) throw new ArgumentNullException(nameof(args)); if (args.Contains(null)) throw new ArgumentNullException(); + DebugUtil.EnsureGIL(); + var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, IntPtr.Zero); t.Dispose(); @@ -690,6 +719,8 @@ public PyObject Invoke(PyTuple args) { if (args == null) throw new ArgumentNullException(nameof(args)); + DebugUtil.EnsureGIL(); + IntPtr r = Runtime.PyObject_Call(obj, args.obj, IntPtr.Zero); Exceptions.ErrorCheck(r); return new PyObject(r); @@ -708,6 +739,8 @@ public PyObject Invoke(PyObject[] args, PyDict kw) if (args == null) throw new ArgumentNullException(nameof(args)); if (args.Contains(null)) throw new ArgumentNullException(); + DebugUtil.EnsureGIL(); + var t = new PyTuple(args); IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw?.obj ?? IntPtr.Zero); t.Dispose(); @@ -727,6 +760,8 @@ public PyObject Invoke(PyTuple args, PyDict kw) { if (args == null) throw new ArgumentNullException(nameof(args)); + DebugUtil.EnsureGIL(); + IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw?.obj ?? IntPtr.Zero); Exceptions.ErrorCheck(r); return new PyObject(r); @@ -862,6 +897,8 @@ public bool IsInstance(PyObject typeOrClass) { if (typeOrClass == null) throw new ArgumentNullException(nameof(typeOrClass)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_IsInstance(obj, typeOrClass.obj); if (r < 0) { @@ -883,6 +920,8 @@ public bool IsSubclass(PyObject typeOrClass) { if (typeOrClass == null) throw new ArgumentNullException(nameof(typeOrClass)); + DebugUtil.EnsureGIL(); + int r = Runtime.PyObject_IsSubclass(obj, typeOrClass.obj); if (r < 0) { @@ -902,6 +941,7 @@ public bool IsSubclass(PyObject typeOrClass) /// public bool IsCallable() { + DebugUtil.EnsureGIL(); return Runtime.PyCallable_Check(obj) != 0; } @@ -915,6 +955,7 @@ public bool IsCallable() /// public bool IsIterable() { + DebugUtil.EnsureGIL(); return Runtime.PyObject_IsIterable(obj); } @@ -928,6 +969,7 @@ public bool IsIterable() /// public bool IsTrue() { + DebugUtil.EnsureGIL(); return Runtime.PyObject_IsTrue(obj) != 0; } @@ -941,6 +983,7 @@ public bool IsTrue() /// public PyList Dir() { + DebugUtil.EnsureGIL(); IntPtr r = Runtime.PyObject_Dir(obj); Exceptions.ErrorCheck(r); return new PyList(r); @@ -956,6 +999,7 @@ public PyList Dir() /// public string Repr() { + DebugUtil.EnsureGIL(); IntPtr strval = Runtime.PyObject_Repr(obj); string result = Runtime.GetManagedString(strval); Runtime.XDecref(strval); @@ -972,6 +1016,7 @@ public string Repr() /// public override string ToString() { + DebugUtil.EnsureGIL(); IntPtr strval = Runtime.PyObject_Unicode(obj); string result = Runtime.GetManagedString(strval); Runtime.XDecref(strval); @@ -996,6 +1041,7 @@ public override bool Equals(object o) { return true; } + DebugUtil.EnsureGIL(); int r = Runtime.PyObject_Compare(obj, ((PyObject)o).obj); if (Exceptions.ErrorOccurred()) { @@ -1015,6 +1061,7 @@ public override bool Equals(object o) /// public override int GetHashCode() { + DebugUtil.EnsureGIL(); return ((ulong)Runtime.PyObject_Hash(obj)).GetHashCode(); } @@ -1036,6 +1083,7 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) public override bool TrySetMember(SetMemberBinder binder, object value) { + DebugUtil.EnsureGIL(); IntPtr ptr = Converter.ToPython(value, value?.GetType()); int r = Runtime.PyObject_SetAttrString(obj, binder.Name, ptr); if (r < 0) @@ -1058,6 +1106,7 @@ private void GetArgs(object[] inargs, CallInfo callInfo, out PyTuple args, out P var namedArgumentCount = callInfo.ArgumentNames.Count; var regularArgumentCount = callInfo.ArgumentCount - namedArgumentCount; + DebugUtil.EnsureGIL(); var argTuple = Runtime.PyTuple_New(regularArgumentCount); for (int i = 0; i < regularArgumentCount; ++i) { @@ -1081,6 +1130,7 @@ private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) { ; } + DebugUtil.EnsureGIL(); IntPtr argtuple = Runtime.PyTuple_New(arg_count); for (var i = 0; i < arg_count; i++) { @@ -1108,6 +1158,7 @@ private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) private static void AddArgument(IntPtr argtuple, int i, object target) { + DebugUtil.EnsureGIL(); IntPtr ptr = GetPythonObject(target); if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0) @@ -1199,6 +1250,7 @@ public override bool TryConvert(ConvertBinder binder, out object result) public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result) { + DebugUtil.EnsureGIL(); IntPtr res; if (!(arg is PyObject)) { @@ -1310,6 +1362,7 @@ private static object CheckNone(PyObject pyObj) public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result) { + DebugUtil.EnsureGIL(); int r; IntPtr res; switch (binder.Operation) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 3ce3eaa1a..d1dc40b6e 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -807,6 +807,8 @@ internal static unsafe long Refcount(IntPtr op) internal static IntPtr PyGILState_GetThisThreadState() => Delegates.PyGILState_GetThisThreadState(); + internal static int PyGILState_Check() => Delegates.PyGILState_Check(); + public static int Py_Main( int argc, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv @@ -1817,6 +1819,9 @@ static Delegates() PyGILState_Ensure = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Ensure), GetUnmanagedDll(PythonDLL))); PyGILState_Release = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Release), GetUnmanagedDll(PythonDLL))); PyGILState_GetThisThreadState = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_GetThisThreadState), GetUnmanagedDll(PythonDLL))); + if (PythonVersion >= new Version(3, 4)) { + PyGILState_Check = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyGILState_Check), GetUnmanagedDll(PythonDLL))); + } Py_Main = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_Main), GetUnmanagedDll(PythonDLL))); PyEval_InitThreads = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_InitThreads), GetUnmanagedDll(PythonDLL))); PyEval_ThreadsInitialized = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyEval_ThreadsInitialized), GetUnmanagedDll(PythonDLL))); @@ -2133,6 +2138,11 @@ static T GetDelegateForFunctionPointer(IntPtr functionPointer) { [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] internal delegate IntPtr PyGILState_GetThisThreadStateDelegate(); + internal static PyGILState_CheckDelegate PyGILState_Check { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyGILState_CheckDelegate(); + internal static Py_MainDelegate Py_Main { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] From e964c6d954e3a074cb7dd50f4a278342b092454d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 26 Sep 2019 14:56:14 -0700 Subject: [PATCH 084/240] removed excessive tracing --- src/runtime/assemblymanager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index 244ee720f..7ed075b25 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -204,6 +204,7 @@ public static Assembly LoadAssembly(string name) { assembly = Assembly.Load(name); } + catch (FileNotFoundException) { } catch (Exception e) { Trace.WriteLine($"{nameof(AssemblyManager)} failed to load assembly {name}: {e}"); @@ -229,6 +230,7 @@ public static Assembly LoadAssemblyPath(string name) { assembly = Assembly.LoadFrom(path); } + catch (FileNotFoundException) { } catch (Exception e) { Trace.WriteLine($"{nameof(AssemblyManager)} failed to load assembly {name}: {e}"); From 5bb10073b674086ff025c267a15b86a7bebc4199 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 15:36:39 -0700 Subject: [PATCH 085/240] ensured, that __call__ can be inherited through multiple levels of hierarchy --- src/embed_tests/CallableObject.cs | 8 ++- src/runtime/classobject.cs | 84 +++++++++++++++++++------------ 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index 395215c90..9df5f49d0 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -23,7 +23,7 @@ public void Dispose() { [Test] public void CallMethodMakesObjectCallable() { - var doubler = new Doubler(); + var doubler = new DerivedDoubler(); using (Py.GIL()) { dynamic applyObjectTo21 = PythonEngine.Eval("lambda o: o(21)"); Assert.AreEqual(doubler.__call__(21), (int)applyObjectTo21(doubler.ToPython())); @@ -43,13 +43,17 @@ class Doubler { public int __call__(int arg) => 2 * arg; } + class DerivedDoubler : Doubler { } + [CustomBaseType] class CallViaInheritance { public const string BaseClassName = "Forwarder"; public static readonly string BaseClassSource = $@" -class {BaseClassName}: +class MyCallableBase: def __call__(self, val): return self.Call(val) + +class {BaseClassName}(MyCallableBase): pass "; public int Call(int arg) => 3 * arg; } diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 02acdc478..468844bb8 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -297,44 +298,31 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) if (cb.type != typeof(Delegate)) { - IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict); - IntPtr methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); - if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) - { - Exceptions.SetError(Exceptions.TypeError, "object is not callable"); - return IntPtr.Zero; - } - - if (GetManagedObject(methodObjectHandle) is MethodObject methodObject) - { - return methodObject.Invoke(ob, args, kw); + var calls = cb.type.GetMethods(BindingFlags.Public | BindingFlags.Instance) + .Where(m => m.Name == "__call__") + .ToList(); + if (calls.Count > 0) { + var callBinder = new MethodBinder(); + foreach (MethodInfo call in calls) { + callBinder.AddMethod(call); + } + return callBinder.Invoke(ob, args, kw); } - methodObjectHandle = IntPtr.Zero; - - foreach (IntPtr pythonBase in GetPythonBases(tp)) { - dict = Marshal.ReadIntPtr(pythonBase, TypeOffset.tp_dict); + using var super = new PyObject(Runtime.SelfIncRef(Runtime.PySuper)); + using var self = new PyObject(Runtime.SelfIncRef(ob)); + using var none = new PyObject(Runtime.SelfIncRef(Runtime.PyNone)); + foreach (IntPtr managedTypeDerivingFromPython in GetTypesWithPythonBasesInHierarchy(tp)) { + using var @base = super.Invoke(new PyObject(managedTypeDerivingFromPython), self); + using var call = @base.GetAttrOrElse("__call__", none); - methodObjectHandle = Runtime.PyDict_GetItemString(dict, "__call__"); - if (methodObjectHandle != IntPtr.Zero && methodObjectHandle != Runtime.PyNone) break; - } + if (call.Handle == Runtime.PyNone) continue; - if (methodObjectHandle == IntPtr.Zero || methodObjectHandle == Runtime.PyNone) { - Exceptions.SetError(Exceptions.TypeError, "object is not callable"); - return IntPtr.Zero; + return Runtime.PyObject_Call(call.Handle, args, kw); } - var boundMethod = Runtime.PyMethod_New(methodObjectHandle, ob); - if (boundMethod == IntPtr.Zero) { return IntPtr.Zero; } - - try - { - return Runtime.PyObject_Call(boundMethod, args, kw); - } - finally - { - Runtime.XDecref(boundMethod); - } + Exceptions.SetError(Exceptions.TypeError, "object is not callable"); + return IntPtr.Zero; } var co = (CLRObject)GetManagedObject(ob); @@ -377,6 +365,38 @@ internal static IEnumerable GetPythonBases(IntPtr tp) { yield return tp; } + internal static IEnumerable GetTypesWithPythonBasesInHierarchy(IntPtr tp) { + Debug.Assert(IsManagedType(tp)); + + var candidateQueue = new Queue(); + candidateQueue.Enqueue(tp); + while (candidateQueue.Count > 0) { + tp = candidateQueue.Dequeue(); + IntPtr bases = Marshal.ReadIntPtr(tp, TypeOffset.tp_bases); + if (bases != IntPtr.Zero) { + long baseCount = Runtime.PyTuple_Size(bases); + bool hasPythonBase = false; + for (long baseIndex = 0; baseIndex < baseCount; baseIndex++) { + IntPtr @base = Runtime.PyTuple_GetItem(bases, baseIndex); + if (IsManagedType(@base)) { + candidateQueue.Enqueue(@base); + } else { + hasPythonBase = true; + } + } + + if (hasPythonBase) yield return tp; + } else { + tp = Marshal.ReadIntPtr(tp, TypeOffset.tp_base); + if (tp != IntPtr.Zero && IsManagedType(tp)) + candidateQueue.Enqueue(tp); + } + } + } + + /// + /// Checks if specified type is a CLR type + /// internal static bool IsManagedType(IntPtr tp) { var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); From 0ff236bc587004fd08f1c29d99aef89ed337e3ed Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 15:37:44 -0700 Subject: [PATCH 086/240] test, that ensures Python-derived classes can set ad-hoc attributes --- src/embed_tests/Inheritance.cs | 33 +++++++++++++++++++++++++++- src/runtime/Python.Runtime.15.csproj | 4 ++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index 83342247d..1771209ef 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -1,5 +1,5 @@ using System; - +using System.Collections.Generic; using NUnit.Framework; using Python.Runtime; @@ -89,6 +89,18 @@ public void PythonCanCallOverridenMethod() { Assert.AreEqual(expected: Inherited.OverridenVirtValue, actual); } } + + [Test] + public void PythonCanSetAdHocAttributes() { + var instance = new Inherited(); + using (Py.GIL()) + using (var scope = Py.CreateScope()) { + scope.Set(nameof(instance), instance); + scope.Exec($"super({nameof(instance)}.__class__, {nameof(instance)}).set_x_to_42()"); + int actual = scope.Eval($"{nameof(instance)}.x"); + Assert.AreEqual(expected: Inherited.X, actual); + } + } } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] @@ -117,6 +129,8 @@ public class InheritanceTestBaseClassWrapper : PythonWrapperBase { @": def virt(self): return 42 + def set_x_to_42(self): + self.x = 42 def callVirt(self): return self.virt() def __getattr__(self, name): @@ -128,6 +142,23 @@ def __setattr__(self, name, value): public class Inherited : InheritanceTestBaseClassWrapper { public const int OverridenVirtValue = -42; + public const int X = 42; + readonly Dictionary extras = new Dictionary(); public int virt() => OverridenVirtValue; + public int x { + get { + using (var scope = Py.CreateScope()) { + scope.Set("this", this); + try { + return scope.Eval("super(this.__class__, this).x"); + } catch (PythonException ex) when (ex.PyType == Exceptions.AttributeError) { + if (this.extras.TryGetValue(nameof(x), out object value)) + return (int)value; + throw; + } + } + } + set => this.extras[nameof(x)] = value; + } } } diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 8fdaeb339..6d45d4a21 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net40 AnyCPU @@ -19,7 +19,7 @@ ..\..\ $(SolutionDir)\bin\ $(PythonBuildDir)\$(TargetFramework)\ - 7.3 + 8.0 True ..\pythonnet.snk $(PYTHONNET_DEFINE_CONSTANTS) From 5095f606584ad2f386114cef228ebdea172d9331 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 15:44:31 -0700 Subject: [PATCH 087/240] fixed access violation / ExecutionEngineException due to incorrect layout of Python-derived .NET types Custom Python base types often had a different layout from `object` due to extra fields. These extra fields would overlap with Python.NET's field used for `GCHandle`. This change introduces new field in CLR Metatype, called clr_gchandle_offset, that lets reflected .NET types to record where GC handle is written in Python object. --- src/runtime/PythonEngineException.cs | 15 ++++++++ src/runtime/clrobject.cs | 2 +- src/runtime/interop.cs | 28 ++++++++++----- src/runtime/metatype.cs | 2 ++ src/runtime/typemanager.cs | 53 ++++++++++++++++++++++------ src/runtime/typeoffset.cs | 2 ++ 6 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 src/runtime/PythonEngineException.cs diff --git a/src/runtime/PythonEngineException.cs b/src/runtime/PythonEngineException.cs new file mode 100644 index 000000000..22059002a --- /dev/null +++ b/src/runtime/PythonEngineException.cs @@ -0,0 +1,15 @@ +namespace Python.Runtime { + using System; + using System.Runtime.Serialization; + + [Serializable] + public class PythonEngineException: Exception { + public PythonEngineException() : base() { } + + public PythonEngineException(string message) : base(message) { } + + public PythonEngineException(string message, Exception innerException) : base(message, innerException) { } + + protected PythonEngineException(SerializationInfo info, StreamingContext context):base(info, context) { } + } +} diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 502677655..65069d01c 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -23,7 +23,7 @@ internal CLRObject(object ob, IntPtr tp) } GCHandle gc = GCHandle.Alloc(this); - Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc); + Marshal.WriteIntPtr(py, ObjectOffset.magic(py), (IntPtr)gc); tpHandle = tp; pyHandle = py; gcHandle = gc; diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 882315913..273bde7cf 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -1,6 +1,6 @@ using System; using System.Collections; -using System.Collections.Specialized; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Reflection; using System.Text; @@ -88,14 +88,30 @@ static ObjectOffset() public static int magic(IntPtr ob) { + if (ob == IntPtr.Zero) throw new ArgumentNullException(nameof(ob)); + if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) { return ExceptionOffset.ob_data; } - return ob_data; + + IntPtr tp = Runtime.PyObject_TYPE(ob); + if (Runtime.PyObject_TYPE(tp) == Runtime.PyCLRMetaType) { + int offset = (int)Marshal.ReadIntPtr(tp, TypeOffset.clr_gchandle_offset); + ClrGcHandleOffsetAssertSanity(offset); + return offset; + } else { + return ob_data; + } } + [Conditional("DEBUG")] + static void AssertIsClrType(IntPtr tp) => Debug.Assert(Runtime.PyObject_TYPE(tp) == Runtime.PyCLRMetaType); + [Conditional("DEBUG")] + internal static void ClrGcHandleOffsetAssertSanity(int offset) + => Debug.Assert(offset > 0 && offset < 1024*1024, "GC handle offset is insane"); + public static int DictOffset(IntPtr ob) { if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || @@ -426,12 +442,8 @@ internal static IntPtr GetThunk(MethodInfo method, string funcType = null) if (dt != null) { - IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size); - Delegate d = Delegate.CreateDelegate(dt, method); - Thunk cb = new Thunk(d); - Marshal.StructureToPtr(cb, tmp, false); - IntPtr fp = Marshal.ReadIntPtr(tmp, 0); - Marshal.FreeHGlobal(tmp); + var d = Delegate.CreateDelegate(dt, method); + IntPtr fp = Marshal.GetFunctionPointerForDelegate(d); keepAlive.Add(d); return fp; } diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 8853c2d5e..f26ace4e1 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -22,6 +22,7 @@ public static IntPtr Initialize() return PyCLRMetaType; } + internal static int ExtraTypeDataSize => IntPtr.Size; /// /// Metatype __new__ implementation. This is called to create a new @@ -108,6 +109,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) Util.WriteCLong(type, TypeOffset.tp_flags, flags); TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc); + TypeManager.CopySlot(base_type, type, TypeOffset.clr_gchandle_offset); // Hmm - the standard subtype_traverse, clear look at ob_size to // do things, so to allow gc to work correctly we need to move diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index f04901583..5f42873e6 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -93,7 +93,8 @@ internal static IntPtr CreateType(Type impl) TypeFlags.HeapType | TypeFlags.HaveGC; Util.WriteCLong(type, TypeOffset.tp_flags, flags); - Runtime.PyType_Ready(type); + if (Runtime.PyType_Ready(type) != 0) + throw new PythonEngineException("Can not create type", PythonException.FromPyErr()); IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); @@ -121,21 +122,18 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) tp_dictoffset = ObjectOffset.DictOffset(Exceptions.Exception); } - IntPtr type = AllocateTypeObject(name); + IntPtr type = AllocateTypeObject(name, typeType: Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); Runtime.XIncref(Runtime.PyCLRMetaType); - Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); - Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); - Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, (IntPtr)tp_dictoffset); - InitializeSlots(type, impl.GetType()); if (typeof(IGetAttr).IsAssignableFrom(clrType)) { InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); } + int extraTypeDataOffset = ob_size - MetaType.ExtraTypeDataSize; try { IntPtr base_ = GetBaseType(clrType, out IntPtr bases); @@ -148,6 +146,20 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Marshal.WriteIntPtr(type, TypeOffset.tp_bases, bases); Runtime.XIncref(bases); } + + int baseSize = checked((int)Marshal.ReadIntPtr(base_, TypeOffset.tp_basicsize)); + if (!ClassObject.IsManagedType(base_)) + { + // custom base type is a Python type, so we must allocate additional space for GC handle + extraTypeDataOffset = baseSize; + ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); + ob_size = baseSize + MetaType.ExtraTypeDataSize; + } else + { + extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(base_, TypeOffset.clr_gchandle_offset)); + ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); + ob_size = baseSize; + } } } catch (Exception error) @@ -156,6 +168,13 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return IntPtr.Zero; } + ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); + + Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); + Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); + Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, (IntPtr)tp_dictoffset); + Marshal.WriteIntPtr(type, TypeOffset.clr_gchandle_offset, (IntPtr)extraTypeDataOffset); + int flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; @@ -387,9 +406,14 @@ internal static IntPtr CreateMetaType(Type impl) Marshal.WriteIntPtr(type, TypeOffset.tp_base, py_type); Runtime.XIncref(py_type); - // Copy gc and other type slots from the base Python metatype. + TypeOffset.clr_gchandle_offset = checked((int)Marshal.ReadIntPtr(py_type, TypeOffset.tp_basicsize)); + if (TypeOffset.clr_gchandle_offset <= 0) + throw new PythonEngineException("CLR Metatype initialization failed: unable to read tp_basicsize correctly"); + ObjectOffset.ClrGcHandleOffsetAssertSanity(TypeOffset.clr_gchandle_offset); + int structSize = TypeOffset.clr_gchandle_offset + MetaType.ExtraTypeDataSize; + Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, new IntPtr(structSize)); - CopySlot(py_type, type, TypeOffset.tp_basicsize); + // Copy gc and other type slots from the base Python metatype. CopySlot(py_type, type, TypeOffset.tp_itemsize); CopySlot(py_type, type, TypeOffset.tp_dictoffset); @@ -430,7 +454,8 @@ internal static IntPtr CreateMetaType(Type impl) Marshal.WriteIntPtr(type, TypeOffset.tp_methods, mdefStart); - Runtime.PyType_Ready(type); + if (Runtime.PyType_Ready(type) != 0) + throw new PythonEngineException("Failed to create CLR Metatype", PythonException.FromPyErr()); IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); IntPtr mod = Runtime.PyString_FromString("CLR"); @@ -445,8 +470,16 @@ internal static IntPtr CreateMetaType(Type impl) /// Utility method to allocate a type object & do basic initialization. /// internal static IntPtr AllocateTypeObject(string name) + => AllocateTypeObject(name, Runtime.PyTypeType); + /// + /// Utility method to allocate a type object & do basic initialization. + /// + internal static IntPtr AllocateTypeObject(string name, IntPtr typeType) { - IntPtr type = Runtime.PyType_GenericAlloc(Runtime.PyTypeType, 0); + if (name == null) throw new ArgumentNullException(nameof(name)); + if (typeType == IntPtr.Zero) throw new ArgumentNullException(nameof(typeType)); + + IntPtr type = Runtime.PyType_GenericAlloc(typeType, 0); // Cheat a little: we'll set tp_name to the internal char * of // the Python version of the type name - otherwise we'd have to diff --git a/src/runtime/typeoffset.cs b/src/runtime/typeoffset.cs index 792a9605e..173ce0ea0 100644 --- a/src/runtime/typeoffset.cs +++ b/src/runtime/typeoffset.cs @@ -31,6 +31,8 @@ public static int magic() return ob_size; } + public static int clr_gchandle_offset = 0; + public static int ob_refcnt = 0; public static int ob_type = 0; public static int ob_size = 0; From 2285f6a5d7d66506ea4336223837bd1c4a4a44f1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 16:30:38 -0700 Subject: [PATCH 088/240] improved handling for params arrays Fixed TypeError when calling .NET method and not passing any elements to params array. Also improved overload resolution error message. --- src/embed_tests/Inheritance.cs | 12 ++++---- src/embed_tests/TestInstanceWrapping.cs | 38 +++++++++++++++++++++++++ src/runtime/methodbinder.cs | 24 +++++++++------- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index 1771209ef..27e728871 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -97,7 +97,7 @@ public void PythonCanSetAdHocAttributes() { using (var scope = Py.CreateScope()) { scope.Set(nameof(instance), instance); scope.Exec($"super({nameof(instance)}.__class__, {nameof(instance)}).set_x_to_42()"); - int actual = scope.Eval($"{nameof(instance)}.x"); + int actual = scope.Eval($"{nameof(instance)}.{nameof(Inherited.XProp)}"); Assert.AreEqual(expected: Inherited.X, actual); } } @@ -130,7 +130,7 @@ public class InheritanceTestBaseClassWrapper : PythonWrapperBase { def virt(self): return 42 def set_x_to_42(self): - self.x = 42 + self.XProp = 42 def callVirt(self): return self.virt() def __getattr__(self, name): @@ -145,20 +145,20 @@ public class Inherited : InheritanceTestBaseClassWrapper { public const int X = 42; readonly Dictionary extras = new Dictionary(); public int virt() => OverridenVirtValue; - public int x { + public int XProp { get { using (var scope = Py.CreateScope()) { scope.Set("this", this); try { - return scope.Eval("super(this.__class__, this).x"); + return scope.Eval($"super(this.__class__, this).{nameof(XProp)}"); } catch (PythonException ex) when (ex.PyType == Exceptions.AttributeError) { - if (this.extras.TryGetValue(nameof(x), out object value)) + if (this.extras.TryGetValue(nameof(this.XProp), out object value)) return (int)value; throw; } } } - set => this.extras[nameof(x)] = value; + set => this.extras[nameof(this.XProp)] = value; } } } diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 6552c8660..2bf3e3fb3 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -37,6 +37,42 @@ public void OverloadResolution_IntOrStr() { } } + [Test] + public void OverloadResolution_ParamsOmitted() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithInt = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42)"); + callWithInt(o); + Assert.AreEqual(42, overloaded.Value); + } + } + + [Test] + public void OverloadResolution_ParamsTypeMatch() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithInts = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, 43)"); + callWithInts(o); + Assert.AreEqual(42, overloaded.Value); + } + } + + [Test] + public void OverloadResolution_ParamsTypeMisMatch() { + var overloaded = new Overloaded(); + using (Py.GIL()) { + var o = overloaded.ToPython(); + + dynamic callWithIntAndStr = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, object())"); + var error = Assert.Throws(() => callWithIntAndStr(o), "Should have thrown PythonException"); + Assert.AreEqual(expected: Exceptions.TypeError, actual: error.PyType, "Should have thrown TypeError"); + } + } + [Test] public void OverloadResolution_ObjOrClass() { var overloaded = new Overloaded(); @@ -122,6 +158,8 @@ public void IntOrStr(string arg) => public void BaseOrDerived(Base _) => this.Value = Base; public void BaseOrDerived(Derived _) => this.Value = Derived; + public void ArgPlusParams(int arg0, params double[] floats) => this.Value = arg0; + public bool TryGetAttr(string name, out PyObject value) { using (var self = this.ToPython()) { if (GetAttr.TryGetBaseAttr(self, name, out value) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 2c2f71763..864b38f5a 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -474,6 +474,15 @@ static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, var match = false; paramsArray = false; + if (parameters.Length > 0 + && Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute))) + { + parameters = parameters.Take(parameters.Length - 1).ToArray(); + // since we have params array, any more parameters is fine + argumentCount = Math.Min(argumentCount, parameters.Length); + paramsArray = true; + } + if (argumentCount == parameters.Length) { match = true; @@ -488,12 +497,6 @@ static bool MatchesArgumentCount(int argumentCount, ParameterInfo[] parameters, defaultArgList.Add(parameters[v].DefaultValue); } } - } else if (argumentCount > parameters.Length && parameters.Length > 0 && - Attribute.IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute))) - { - // This is a `foo(params object[] bar)` style method - match = true; - paramsArray = true; } return match; @@ -517,17 +520,18 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i if (binding == null) { + var methods = methodinfo ?? this.methods; var value = new StringBuilder("No method matches given arguments"); - if (methodinfo != null && methodinfo.Length > 0) { + if (methods != null && methods.Length > 0) { value.Append(" for "); if (inst != IntPtr.Zero && inst != Runtime.PyNone) { value.Append(Runtime.PyObject_GetTypeName(inst)); - value.Append(methodinfo[0].IsStatic ? "::": "."); + value.Append(methods[0].IsStatic ? "::": "."); } else { - value.Append(methodinfo[0].DeclaringType.Name); + value.Append(methods[0].DeclaringType.Name); value.Append("::"); } - value.Append(methodinfo[0].Name); + value.Append(methods[0].Name); } long argCount = Runtime.PyTuple_Size(args); From 7e9e721555ef72aedaa347be2a3b83a2fc87ea0c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 21:30:04 -0700 Subject: [PATCH 089/240] allow excluding public .NET types from being exposed to Python Introduced PyExportAttribute and handling for it in ScanAssembly --- src/runtime/PyExportAttribute.cs | 12 ++++++++++++ src/runtime/assemblymanager.cs | 11 ++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 src/runtime/PyExportAttribute.cs diff --git a/src/runtime/PyExportAttribute.cs b/src/runtime/PyExportAttribute.cs new file mode 100644 index 000000000..98e63cf42 --- /dev/null +++ b/src/runtime/PyExportAttribute.cs @@ -0,0 +1,12 @@ +namespace Python.Runtime { + using System; + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum + | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Assembly, + AllowMultiple = false, + Inherited = false)] + public class PyExportAttribute : Attribute { + internal readonly bool Export; + public PyExportAttribute(bool export) { this.Export = export; } + } +} diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index 7ed075b25..f85ede5df 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -351,6 +351,9 @@ public static bool LoadImplicit(string name, bool warn = true) /// internal static void ScanAssembly(Assembly assembly) { + if (assembly.GetCustomAttribute()?.Export == false) { + return; + } // A couple of things we want to do here: first, we want to // gather a list of all of the namespaces contributed to by // the assembly. @@ -476,19 +479,19 @@ internal static Type[] GetTypes(Assembly a) { try { - return a.GetTypes(); + return a.GetTypes().Where(IsExported).ToArray(); } catch (ReflectionTypeLoadException exc) { // Return all types that were successfully loaded - return exc.Types.Where(x => x != null).ToArray(); + return exc.Types.Where(x => x != null && IsExported(x)).ToArray(); } } else { try { - return a.GetExportedTypes(); + return a.GetExportedTypes().Where(IsExported).ToArray(); } catch (FileNotFoundException) { @@ -496,5 +499,7 @@ internal static Type[] GetTypes(Assembly a) } } } + + static bool IsExported(Type type) => type.GetCustomAttribute()?.Export != false; } } From cb9aa80a438e99026f005ca2c448d4443c4efcb3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 21:30:36 -0700 Subject: [PATCH 090/240] improved documentation for MethodBinding --- src/runtime/methodbinding.cs | 29 +++++++++++++++++++++++------ src/runtime/methodobject.cs | 12 ++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index 27987796d..9f9e006d1 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -63,23 +63,26 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) PyObject Singature { get { var infos = this.info == null ? this.m.info : new[] {this.info}; + var type = infos.Select(i => i.DeclaringType) + .OrderByDescending(t => t, new TypeSpecificityComparer()) + .First(); + infos = infos.Where(info => info.DeclaringType == type).ToArray(); // this is a primitive version // the overload with the maximum number of parameters should be used - var primary = infos.First(); + var primary = infos.OrderByDescending(i => i.GetParameters().Length).First(); var primaryParameters = primary.GetParameters(); PyObject signatureClass = Runtime.InspectModule.GetAttr("Signature"); var primaryReturn = primary.ReturnParameter; - if (infos.Any(i => i.GetParameters().Length != primaryParameters.Length - || i.ReturnParameter?.ParameterType != primaryReturn?.ParameterType)) { - return signatureClass.Invoke(); - } var parameters = new PyList(); var parameterClass = primaryParameters.Length > 0 ? Runtime.InspectModule.GetAttr("Parameter") : null; var positionalOrKeyword = primaryParameters.Length > 0 ? parameterClass.GetAttr("POSITIONAL_OR_KEYWORD") : null; for (int i = 0; i < primaryParameters.Length; i++) { var parameter = primaryParameters[i]; - var alternatives = infos.Select(info => info.GetParameters()[i]); + var alternatives = infos.Select(info => { + ParameterInfo[] altParamters = info.GetParameters(); + return i < altParamters.Length ? altParamters[i] : null; + }).Where(p => p != null); var defaultValue = alternatives .Select(alternative => alternative.DefaultValue != DBNull.Value ? alternative.DefaultValue.ToPython() : null) .FirstOrDefault(v => v != null) ?? parameterClass.GetAttr("empty"); @@ -102,6 +105,15 @@ PyObject Singature { } } + struct TypeSpecificityComparer : IComparer { + public int Compare(Type a, Type b) { + if (a == b) return 0; + if (a.IsSubclassOf(b)) return 1; + if (b.IsSubclassOf(a)) return -1; + throw new NotSupportedException(); + } + } + /// /// MethodBinding __getattribute__ implementation. /// @@ -130,6 +142,11 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) case "__signature__": var sig = self.Singature; return sig.Handle; + case "__name__": + var pyName = self.m.GetName(); + return pyName == IntPtr.Zero + ? IntPtr.Zero + : Runtime.SelfIncRef(pyName); default: return Runtime.PyObject_GenericGetAttr(ob, key); } diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index 8df9c8029..96619a22d 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace Python.Runtime @@ -90,6 +92,16 @@ internal IntPtr GetDocString() return doc; } + internal IntPtr GetName() + { + var names = new HashSet(binder.GetMethods().Select(m => m.Name)); + if (names.Count != 1) { + Exceptions.SetError(Exceptions.AttributeError, "a method has no name"); + return IntPtr.Zero; + } + return Runtime.PyString_FromString(names.First()); + } + /// /// This is a little tricky: a class can actually have a static method From cb3bdbbd63c6e77a9fe314338302e5125f8f1d3c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 21:31:02 -0700 Subject: [PATCH 091/240] added PyObject.Clone, that allows creating copies of PyObjects --- src/runtime/pyobject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 24c33af47..fd6e7541b 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -1412,5 +1412,7 @@ public override IEnumerable GetDynamicMemberNames() yield return pyObj.ToString(); } } + + public PyObject Clone() => new PyObject(Runtime.SelfIncRef(this.Handle)); } } From afd5033bf7c45f65600eae2f540427e6c3d17ea3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 27 Sep 2019 22:09:47 -0700 Subject: [PATCH 092/240] handle exceptions in custom GetAttr --- src/runtime/slots.cs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index 9f657e757..a252ee269 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -21,9 +21,28 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { var self = (IGetAttr)((CLRObject)ManagedType.GetManagedObject(ob)).inst; string attr = Runtime.GetManagedString(key); RuntimeHelpers.EnsureSufficientExecutionStack(); - return self.TryGetAttr(attr, out var value) - ? Runtime.SelfIncRef(value.Handle) - : Runtime.PyObject_GenericGetAttr(ob, key); + bool gotAttr; + PyObject value; + try { + gotAttr = self.TryGetAttr(attr, out value); + } catch (Exception error) { + Exceptions.SetError(error); + return IntPtr.Zero; + } + if (gotAttr) { + if (value == null || value.Handle == IntPtr.Zero) { + Exceptions.SetError(Exceptions.ValueError, + nameof(IGetAttr) + " implementation returned null value"); + return IntPtr.Zero; + } + + return Runtime.SelfIncRef(value.Handle); + } else { + IntPtr result = Runtime.PyObject_GenericGetAttr(ob, key); + System.Diagnostics.Debug.Assert(result != IntPtr.Zero + || Exceptions.ErrorOccurred()); + return result; + } } } From 1a23334dcca638cfdff662ab083f166854a5deff Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 1 Oct 2019 23:16:48 -0700 Subject: [PATCH 093/240] refactored native library loading code --- src/runtime/Platforms/INativeLibraryLoader.cs | 9 ++ src/runtime/Platforms/LinuxLibraryLoader.cs | 39 ++++++ src/runtime/Platforms/MacLibraryLoader.cs | 38 ++++++ src/runtime/Platforms/UnixLibraryLoader.cs | 33 +++++ src/runtime/Platforms/WindowsLibraryLoader.cs | 22 +++ src/runtime/runtime.cs | 129 +----------------- 6 files changed, 148 insertions(+), 122 deletions(-) create mode 100644 src/runtime/Platforms/INativeLibraryLoader.cs create mode 100644 src/runtime/Platforms/LinuxLibraryLoader.cs create mode 100644 src/runtime/Platforms/MacLibraryLoader.cs create mode 100644 src/runtime/Platforms/UnixLibraryLoader.cs create mode 100644 src/runtime/Platforms/WindowsLibraryLoader.cs diff --git a/src/runtime/Platforms/INativeLibraryLoader.cs b/src/runtime/Platforms/INativeLibraryLoader.cs new file mode 100644 index 000000000..83393f128 --- /dev/null +++ b/src/runtime/Platforms/INativeLibraryLoader.cs @@ -0,0 +1,9 @@ +namespace Python.Runtime.Platforms { + using System; + + interface INativeLibraryLoader { + IntPtr LoadLibrary(string path); + IntPtr GetProcAddress(IntPtr library, string functionName); + void FreeLibrary(IntPtr library); + } +} diff --git a/src/runtime/Platforms/LinuxLibraryLoader.cs b/src/runtime/Platforms/LinuxLibraryLoader.cs new file mode 100644 index 000000000..0957c6eb9 --- /dev/null +++ b/src/runtime/Platforms/LinuxLibraryLoader.cs @@ -0,0 +1,39 @@ +namespace Python.Runtime.Platforms { + using System; + using System.Runtime.InteropServices; + + sealed class LinuxLibraryLoader: UnixLibraryLoader { + public static LinuxLibraryLoader Instance { get; } = new LinuxLibraryLoader(); + + const int RTLD_GLOBAL = 0x100; + const string LinuxNativeDll = "libdl.so"; + public override IntPtr LoadLibrary(string path) { + path = string.IsNullOrEmpty(System.IO.Path.GetExtension(path)) ? $"lib{path}.so" : path; + return Linux.dlopen(path, RTLD_NOW | RTLD_GLOBAL); + } + + public override void FreeLibrary(IntPtr library) => Linux.dlclose(library); + + protected override IntPtr dlerror() => Linux.dlerror(); + + protected override IntPtr dlsym(IntPtr libraryHandle, string name) => Linux.dlsym(libraryHandle, name); + + protected override IntPtr RTLD_DEFAULT => IntPtr.Zero; + + static class Linux { + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlopen(string fileName, int flags); + + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int dlclose(IntPtr handle); + + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr dlerror(); + + [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + + private LinuxLibraryLoader() { } + } +} diff --git a/src/runtime/Platforms/MacLibraryLoader.cs b/src/runtime/Platforms/MacLibraryLoader.cs new file mode 100644 index 000000000..130e277cb --- /dev/null +++ b/src/runtime/Platforms/MacLibraryLoader.cs @@ -0,0 +1,38 @@ +namespace Python.Runtime.Platforms { + using System; + using System.Runtime.InteropServices; + + class MacLibraryLoader: UnixLibraryLoader { + public static MacLibraryLoader Instance { get; } = new MacLibraryLoader(); + const int RTLD_GLOBAL = 0x8; + public override IntPtr LoadLibrary(string path) { + path = string.IsNullOrEmpty(System.IO.Path.GetExtension(path)) ? $"lib{path}.dylib" : path; + return Mac.dlopen(path, RTLD_NOW | RTLD_GLOBAL); + } + + public override void FreeLibrary(IntPtr library) => Mac.dlclose(library); + + protected override IntPtr dlerror() => Mac.dlerror(); + + protected override IntPtr dlsym(IntPtr libraryHandle, string name) => Mac.dlsym(libraryHandle, name); + + protected override IntPtr RTLD_DEFAULT => new IntPtr(-2); + + static class Mac { + const string MacNativeDll = "/usr/lib/libSystem.dylib"; + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr dlopen(String fileName, int flags); + + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal static extern IntPtr dlsym(IntPtr handle, String symbol); + + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern int dlclose(IntPtr handle); + + [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr dlerror(); + } + + private MacLibraryLoader() { } + } +} diff --git a/src/runtime/Platforms/UnixLibraryLoader.cs b/src/runtime/Platforms/UnixLibraryLoader.cs new file mode 100644 index 000000000..b7f11aaf1 --- /dev/null +++ b/src/runtime/Platforms/UnixLibraryLoader.cs @@ -0,0 +1,33 @@ +namespace Python.Runtime.Platforms { + using System; + using System.Runtime.InteropServices; + + abstract class UnixLibraryLoader: INativeLibraryLoader { + protected const int RTLD_NOW = 0x2; + public abstract IntPtr LoadLibrary(string path); + + public IntPtr GetProcAddress(IntPtr libraryHandle, string functionName) { + // look in the exe if dllHandle is NULL + if (libraryHandle == IntPtr.Zero) { + libraryHandle = RTLD_DEFAULT; + } + + // clear previous errors if any + IntPtr res, errPtr; + this.dlerror(); + res = this.dlsym(libraryHandle, functionName); + errPtr = this.dlerror(); + + if (errPtr != IntPtr.Zero) { + throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr)); + } + return res; + } + + protected abstract IntPtr dlerror(); + protected abstract IntPtr dlsym(IntPtr libraryHandle, string name); + protected abstract IntPtr RTLD_DEFAULT { get; } + + public abstract void FreeLibrary(IntPtr library); + } +} diff --git a/src/runtime/Platforms/WindowsLibraryLoader.cs b/src/runtime/Platforms/WindowsLibraryLoader.cs new file mode 100644 index 000000000..30905b776 --- /dev/null +++ b/src/runtime/Platforms/WindowsLibraryLoader.cs @@ -0,0 +1,22 @@ +namespace Python.Runtime.Platforms { + using System; + using System.Runtime.InteropServices; + + class WindowsLibraryLoader : INativeLibraryLoader { + public static WindowsLibraryLoader Instance { get; } = new WindowsLibraryLoader(); + public void FreeLibrary(IntPtr library) => WinFreeLibrary(library); + public IntPtr GetProcAddress(IntPtr library, string functionName) => WinGetProcAddress(library, functionName); + public IntPtr LoadLibrary(string path) => WinLoadLibrary(path); + + private const string WinNativeDll = "kernel32.dll"; + + [DllImport(WinNativeDll, EntryPoint = "LoadLibrary")] + public static extern IntPtr WinLoadLibrary(string dllToLoad); + [DllImport(WinNativeDll, EntryPoint = "GetProcAddress")] + public static extern IntPtr WinGetProcAddress(IntPtr hModule, string procedureName); + [DllImport(WinNativeDll, EntryPoint = "FreeLibrary")] + public static extern bool WinFreeLibrary(IntPtr hModule); + + private WindowsLibraryLoader() { } + } +} diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index d1dc40b6e..70cea242e 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -6,138 +6,23 @@ using System.Text; using System.Collections.Generic; +using Python.Runtime.Platforms; + namespace Python.Runtime { - [SuppressUnmanagedCodeSecurity] internal static class NativeMethods { - private static int RTLD_NOW = 0x2; -// MONO_LINUX - private static int LINUX_RTLD_GLOBAL = 0x100; - private static IntPtr LINUX_RTLD_DEFAULT = IntPtr.Zero; - private const string LinuxNativeDll = "libdl.so"; - public static IntPtr LinuxLoadLibrary(string fileName) - { - fileName = string.IsNullOrEmpty(System.IO.Path.GetExtension(fileName)) ? $"lib{fileName}.so" : fileName; - return Linux.dlopen(fileName, RTLD_NOW | LINUX_RTLD_GLOBAL); - } -// MONO_OSX - private static int MAC_RTLD_GLOBAL = 0x8; - private const string MacNativeDll = "/usr/lib/libSystem.dylib"; - private static IntPtr MAC_RTLD_DEFAULT = new IntPtr(-2); - - public static IntPtr MacLoadLibrary(string fileName) - { - fileName = string.IsNullOrEmpty(System.IO.Path.GetExtension(fileName)) ? $"lib{fileName}.dylib" : fileName; - return Mac.dlopen(fileName, RTLD_NOW | MAC_RTLD_GLOBAL); - } - - static readonly IntPtr? RTLD_DEFAULT = - RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? LINUX_RTLD_DEFAULT - : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MAC_RTLD_DEFAULT - : (IntPtr?)null; - - public static IntPtr UnixGetProcAddress(IntPtr dllHandle, string name) - { - // look in the exe if dllHandle is NULL - if (dllHandle == IntPtr.Zero) - { - dllHandle = RTLD_DEFAULT.Value; - } - - // clear previous errors if any - IntPtr res, errPtr; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - Linux.dlerror(); - res = Linux.dlsym(dllHandle, name); - errPtr = Linux.dlerror(); - } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - Mac.dlerror(); - res = Mac.dlsym(dllHandle, name); - errPtr = Mac.dlerror(); - } else { - throw new PlatformNotSupportedException(); - } - - if (errPtr != IntPtr.Zero) - { - throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr)); - } - return res; - } - - static class Linux - { - [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlopen(String fileName, int flags); - - [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - internal static extern IntPtr dlsym(IntPtr handle, String symbol); - - [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int dlclose(IntPtr handle); - - [DllImport(LinuxNativeDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr dlerror(); - } - - static class Mac - { - [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr dlopen(String fileName, int flags); - - [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - internal static extern IntPtr dlsym(IntPtr handle, String symbol); - - [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern int dlclose(IntPtr handle); - - [DllImport(MacNativeDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr dlerror(); - } - - // #else // Windows - private const string WinNativeDll = "kernel32.dll"; - - [DllImport(WinNativeDll, EntryPoint = "LoadLibrary")] - public static extern IntPtr WinLoadLibrary(string dllToLoad); - - [DllImport(WinNativeDll, EntryPoint = "GetProcAddress")] - public static extern IntPtr WinGetProcAddress(IntPtr hModule, string procedureName); - - [DllImport(WinNativeDll, EntryPoint = "FreeLibrary")] - public static extern bool WinFreeLibrary(IntPtr hModule); -// #endif public static IntPtr LoadLibrary(string dllToLoad) => impl.LoadLibrary(dllToLoad); - public static IntPtr GetProcAddress(IntPtr hModule, string procedureName) => impl.GetProcAddress(hModule, procedureName); - public static void FreeLibrary(IntPtr hModule) => impl.FreeLibrary(hModule); - - static readonly NativeMethodsImpl impl = - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new NativeMethodsImpl { - LoadLibrary = WinLoadLibrary, - GetProcAddress = WinGetProcAddress, - FreeLibrary = h => WinFreeLibrary(h), - } : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? new NativeMethodsImpl { - LoadLibrary = LinuxLoadLibrary, - GetProcAddress = UnixGetProcAddress, - FreeLibrary = h => Linux.dlclose(h), - } : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? new NativeMethodsImpl { - LoadLibrary = MacLoadLibrary, - GetProcAddress = UnixGetProcAddress, - FreeLibrary = h => Mac.dlclose(h), - } : Throw(new PlatformNotSupportedException()); - - struct NativeMethodsImpl - { - public Func LoadLibrary { get; set; } - public Func GetProcAddress { get; set; } - public Action FreeLibrary { get; set; } - } + static readonly INativeLibraryLoader impl = + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? WindowsLibraryLoader.Instance + : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? LinuxLibraryLoader.Instance + : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MacLibraryLoader.Instance + : Throw(new PlatformNotSupportedException()); internal static T Throw(Exception exception) { From 6c41824f7d3293214c4e9dc96ea3deb61aed62e1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 15 Oct 2019 17:30:31 -0700 Subject: [PATCH 094/240] on NETFX enable overriding OSPlatform detection --- src/runtime/runtime.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 70cea242e..bf7c34e78 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -3048,10 +3048,11 @@ enum Py2 { } } #if NETFX - static class RuntimeInformation{ - public static bool IsOSPlatform(OSPlatform platform){return platform == OSPlatform.Windows;} + public static class RuntimeInformation { + public static OSPlatform OSPlatform { get; set; } = Environment.OSVersion.Platform == PlatformID.Unix ? OSPlatform.Linux : OSPlatform.Windows; + public static bool IsOSPlatform(OSPlatform platform){return platform == OSPlatform;} } - enum OSPlatform{ Windows, Linux, OSX } + public enum OSPlatform{ Windows, Linux, OSX } #endif } From 2f0635aa9b0afe84e42f32d179e93ce0656cec23 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 8 Jan 2020 17:30:10 -0800 Subject: [PATCH 095/240] allow users to create PySequence --- src/runtime/pysequence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs index e2746aa29..044a98b63 100644 --- a/src/runtime/pysequence.cs +++ b/src/runtime/pysequence.cs @@ -12,7 +12,7 @@ namespace Python.Runtime /// public class PySequence : PyObject, IEnumerable { - protected PySequence(IntPtr ptr) : base(ptr) + public PySequence(IntPtr ptr) : base(ptr) { } From 97b033edcd8717c21493d797b39a025fabc3de73 Mon Sep 17 00:00:00 2001 From: amos402 Date: Sun, 24 Jun 2018 16:52:34 +0800 Subject: [PATCH 096/240] Add StackTrace of C# exception --- src/runtime/pythonexception.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 44389a4a5..f46af2ff6 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -205,7 +205,7 @@ public override string Message /// public override string StackTrace { - get { return this._traceback; } + get { return this._traceback + base.StackTrace; } } /// From 2d7c795160856000fcf8341edbf6b6b31991f7f0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 12 Feb 2020 16:22:29 -0800 Subject: [PATCH 097/240] improve StackTrace in PythonException --- src/runtime/pythonexception.cs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index f46af2ff6..df7ccfad7 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -2,6 +2,8 @@ namespace Python.Runtime { + using System.Text; + /// /// Provides a managed interface to exceptions thrown by the Python /// runtime. @@ -46,12 +48,7 @@ public PythonException() } if (_pyTB != IntPtr.Zero) { - PyObject tb_module = PythonEngine.ImportModule("traceback"); - Runtime.XIncref(_pyTB); - using (var pyTB = new PyObject(_pyTB)) - { - this._traceback = tb_module.InvokeMethod("format_tb", pyTB).ToString(); - } + this._traceback = TracebackHandleToString(_pyTB); } PythonEngine.ReleaseLock(gs); } @@ -116,18 +113,28 @@ static PythonException FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntP } if (pyTracebackHandle != IntPtr.Zero) { - PyObject tb_module = PythonEngine.ImportModule("traceback"); - Runtime.XIncref(pyTracebackHandle); - using (var pyTB = new PyObject(pyTracebackHandle)) - { - traceback = tb_module.InvokeMethod("format_tb", pyTB).ToString(); - } + traceback = TracebackHandleToString(pyTracebackHandle); } return new PythonException(pyTypeHandle, pyValueHandle, pyTracebackHandle, msg, pythonTypeName, traceback, inner); } + static string TracebackHandleToString(IntPtr tracebackHandle) { + if (tracebackHandle == IntPtr.Zero) { + throw new ArgumentNullException(nameof(tracebackHandle)); + } + + PyObject tracebackModule = PythonEngine.ImportModule("traceback"); + PyObject traceback = new PyObject(tracebackHandle); + PyList stackLines = new PyList(tracebackModule.InvokeMethod("format_tb", traceback)); + var result = new StringBuilder(); + foreach (object stackLine in stackLines) { + result.Append(stackLine); + } + return result.ToString(); + } + // Ensure that encapsulated Python objects are decref'ed appropriately // when the managed exception wrapper is garbage-collected. From e5dab8abda61af50cebe79a5938bd2a423d2b9d9 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 19 Feb 2020 21:26:07 -0800 Subject: [PATCH 098/240] fixed base type not being set on .NET types without BaseTypeAttribute --- src/embed_tests/TestCallbacks.cs | 12 ++++++++++++ src/runtime/BaseTypeAttributeBase.cs | 4 +++- src/runtime/typemanager.cs | 7 ++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index ced2952bc..b70951385 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -79,6 +79,18 @@ public void TestNoStaticOverloadException() { } } + [Test] + public void TestExceptionInCallback() { + var dotnetFunction = new Action(_ => throw new ArgumentOutOfRangeException()); + using (Py.GIL()) { + dynamic callWith42 = PythonEngine.Eval("lambda f: f(42)"); + var error = Assert.Throws(() => callWith42(dotnetFunction.ToPython())); + Assert.AreEqual( + ClassManager.GetClass(typeof(ArgumentOutOfRangeException)).pyHandle, + error.PyType); + } + } + class FunctionContainer { public void Instance(int arg) { } public static void Static(int arg) { } diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs index b8be479ea..e3bb6d2c3 100644 --- a/src/runtime/BaseTypeAttributeBase.cs +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -27,7 +27,9 @@ public virtual PyTuple BaseTypes(Type type) { return PyTuple.FromSingleElement(bc.pyHandle); } - return null; + return new PyTuple(); } + + internal static BaseTypeAttributeBase Default { get; } = new BaseTypeAttributeBase(); } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 5f42873e6..ac3732f94 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -273,9 +273,10 @@ static IntPtr GetBaseType(Type clrType, out IntPtr baseTypes) return Exceptions.Exception; } - var baseOverride = Util.GetLatestAttribute(clrType); - var types = baseOverride?.BaseTypes(clrType); - if (types == null || types.Length() == 0) return IntPtr.Zero; + var baseOverride = Util.GetLatestAttribute(clrType) + ?? BaseTypeAttributeBase.Default; + var types = baseOverride.BaseTypes(clrType); + if (types.Length() == 0) return IntPtr.Zero; for (int index = 0; index < types.Length(); index++) { IntPtr baseType = Runtime.PyTuple_GetItem(types.Handle, index); if (!PyType.IsTypeType(baseType)) { From 5df70ddf5e829014396619992a767aa0d2abec92 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 19 Feb 2020 21:56:22 -0800 Subject: [PATCH 099/240] when CLR raises an exception, and that exception bubbles up through Python back to CLR, rethrow the original CLR exception instead of PythonException --- src/embed_tests/TestCallbacks.cs | 5 +--- src/runtime/delegatemanager.cs | 3 +-- src/runtime/exceptions.cs | 4 +-- src/runtime/pydict.cs | 2 +- src/runtime/pylist.cs | 10 ++++---- src/runtime/pyobject.cs | 22 ++++++++-------- src/runtime/pyscope.cs | 16 ++++++------ src/runtime/pysequence.cs | 12 ++++----- src/runtime/pythonengine.cs | 2 +- src/runtime/pythonexception.cs | 44 +++++++++++++++++++++++++------- src/runtime/runtime.cs | 6 ++--- src/runtime/slots.cs | 2 +- 12 files changed, 75 insertions(+), 53 deletions(-) diff --git a/src/embed_tests/TestCallbacks.cs b/src/embed_tests/TestCallbacks.cs index b70951385..442fca4b4 100644 --- a/src/embed_tests/TestCallbacks.cs +++ b/src/embed_tests/TestCallbacks.cs @@ -84,10 +84,7 @@ public void TestExceptionInCallback() { var dotnetFunction = new Action(_ => throw new ArgumentOutOfRangeException()); using (Py.GIL()) { dynamic callWith42 = PythonEngine.Eval("lambda f: f(42)"); - var error = Assert.Throws(() => callWith42(dotnetFunction.ToPython())); - Assert.AreEqual( - ClassManager.GetClass(typeof(ArgumentOutOfRangeException)).pyHandle, - error.PyType); + Assert.Throws(() => callWith42(dotnetFunction.ToPython())); } } diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 080aa6c84..2da9808c7 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -243,8 +243,7 @@ public object TrueDispatch(ArrayList args) if (op == IntPtr.Zero) { - var e = PythonException.FromPyErr(); - throw e; + throw PythonException.ThrowLastAsClrException(); } if (rtype == typeof(void)) diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 76d1e0b5f..65126a000 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -172,7 +172,7 @@ internal static IntPtr ErrorCheck(IntPtr pointer) { if (pointer == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return pointer; @@ -185,7 +185,7 @@ internal static IntPtr ErrorOccurredCheck(IntPtr pointer) { if (pointer == IntPtr.Zero || ErrorOccurred()) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return pointer; diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs index 7ea5b8cb0..360809d09 100644 --- a/src/runtime/pydict.cs +++ b/src/runtime/pydict.cs @@ -165,7 +165,7 @@ public void Update(PyObject other) int result = Runtime.PyDict_Update(obj, other.obj); if (result < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } diff --git a/src/runtime/pylist.cs b/src/runtime/pylist.cs index 93e885416..b71ba8799 100644 --- a/src/runtime/pylist.cs +++ b/src/runtime/pylist.cs @@ -72,7 +72,7 @@ public PyList(PyObject[] items) int r = Runtime.PyList_SetItem(obj, i, ptr); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } } @@ -117,7 +117,7 @@ public void Append(PyObject item) int r = Runtime.PyList_Append(obj, item.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -132,7 +132,7 @@ public void Insert(int index, PyObject item) int r = Runtime.PyList_Insert(obj, index, item.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -148,7 +148,7 @@ public void Reverse() int r = Runtime.PyList_Reverse(obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -164,7 +164,7 @@ public void Sort() int r = Runtime.PyList_Sort(obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index fd6e7541b..b65e846f5 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -272,7 +272,7 @@ public PyObject GetAttrOrElse(string name, PyObject _default) { if (!Exceptions.ExceptionMatches(Exceptions.AttributeError)) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } Runtime.PyErr_Clear(); @@ -343,7 +343,7 @@ public void SetAttr(string name, PyObject value) int r = Runtime.PyObject_SetAttrString(obj, name, value.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -366,7 +366,7 @@ public void SetAttr(PyObject name, PyObject value) int r = Runtime.PyObject_SetAttr(obj, name.obj, value.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -387,7 +387,7 @@ public void DelAttr(string name) int r = Runtime.PyObject_SetAttrString(obj, name, IntPtr.Zero); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -409,7 +409,7 @@ public void DelAttr(PyObject name) int r = Runtime.PyObject_SetAttr(obj, name.obj, IntPtr.Zero); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -431,7 +431,7 @@ public virtual PyObject GetItem(PyObject key) IntPtr op = Runtime.PyObject_GetItem(obj, key.obj); if (op == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return new PyObject(op); } @@ -491,7 +491,7 @@ public virtual void SetItem(PyObject key, PyObject value) int r = Runtime.PyObject_SetItem(obj, key.obj, value.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -552,7 +552,7 @@ public virtual void DelItem(PyObject key) int r = Runtime.PyObject_DelItem(obj, key.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -1045,7 +1045,7 @@ public override bool Equals(object o) int r = Runtime.PyObject_Compare(obj, ((PyObject)o).obj); if (Exceptions.ErrorOccurred()) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return r == 0; } @@ -1088,7 +1088,7 @@ public override bool TrySetMember(SetMemberBinder binder, object value) int r = Runtime.PyObject_SetAttrString(obj, binder.Name, ptr); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } Runtime.XDecref(ptr); return true; @@ -1163,7 +1163,7 @@ private static void AddArgument(IntPtr argtuple, int i, object target) if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index 7dca4db2f..36207db92 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -185,7 +185,7 @@ public void ImportAll(PyScope scope) int result = Runtime.PyDict_Update(variables, scope.variables); if (result < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -205,7 +205,7 @@ public void ImportAll(PyObject module) int result = Runtime.PyDict_Update(variables, module_dict); if (result < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -220,7 +220,7 @@ public void ImportAll(PyDict dict) int result = Runtime.PyDict_Update(variables, dict.obj); if (result < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -321,7 +321,7 @@ private void Exec(string code, IntPtr _globals, IntPtr _locals) Runtime.CheckExceptionOccurred(); if (ptr != Runtime.PyNone) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } Runtime.XDecref(ptr); } @@ -348,7 +348,7 @@ private void Set(string name, IntPtr value) int r = Runtime.PyObject_SetItem(variables, pyKey.obj, value); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } } @@ -367,7 +367,7 @@ public void Remove(string name) int r = Runtime.PyObject_DelItem(variables, pyKey.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } } @@ -422,7 +422,7 @@ public bool TryGet(string name, out PyObject value) IntPtr op = Runtime.PyObject_GetItem(variables, pyKey.obj); if (op == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } if (op == Runtime.PyNone) { @@ -555,7 +555,7 @@ internal PyScope NewScope(string name) var module = Runtime.PyModule_New(name); if (module == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return new PyScope(module, this); } diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs index 044a98b63..846b65525 100644 --- a/src/runtime/pysequence.cs +++ b/src/runtime/pysequence.cs @@ -45,7 +45,7 @@ public PyObject GetSlice(int i1, int i2) IntPtr op = Runtime.PySequence_GetSlice(obj, i1, i2); if (op == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return new PyObject(op); } @@ -62,7 +62,7 @@ public void SetSlice(int i1, int i2, PyObject v) int r = Runtime.PySequence_SetSlice(obj, i1, i2, v.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -78,7 +78,7 @@ public void DelSlice(int i1, int i2) int r = Runtime.PySequence_DelSlice(obj, i1, i2); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -114,7 +114,7 @@ public bool Contains(PyObject item) int r = Runtime.PySequence_Contains(obj, item.obj); if (r < 0) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return r != 0; } @@ -132,7 +132,7 @@ public PyObject Concat(PyObject other) IntPtr op = Runtime.PySequence_Concat(obj, other.obj); if (op == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return new PyObject(op); } @@ -150,7 +150,7 @@ public PyObject Repeat(int count) IntPtr op = Runtime.PySequence_Repeat(obj, count); if (op == IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } return new PyObject(op); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index b0d71c112..697380227 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -524,7 +524,7 @@ public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = nu PyObject result = RunString(code, globals, locals, RunFlagType.File); if (result.obj != Runtime.PyNone) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } result.Dispose(); } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index df7ccfad7..f88e9d5fc 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -2,6 +2,7 @@ namespace Python.Runtime { + using System.Runtime.ExceptionServices; using System.Text; /// @@ -22,7 +23,7 @@ public class PythonException : System.Exception public PythonException() { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB); + Runtime.PyErr_Fetch(out _pyType, out _pyValue, out _pyTB); Runtime.XIncref(_pyType); Runtime.XIncref(_pyValue); Runtime.XIncref(_pyTB); @@ -66,24 +67,49 @@ private PythonException(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTrac _traceback = traceback ?? _traceback; } - internal static PythonException FromPyErr() { + internal static Exception FromPyErr() { IntPtr gs = PythonEngine.AcquireLock(); - IntPtr pyTypeHandle = IntPtr.Zero, pyValueHandle = IntPtr.Zero, pyTracebackHandle = IntPtr.Zero; - Runtime.PyErr_Fetch(ref pyTypeHandle, ref pyValueHandle, ref pyTracebackHandle); - Runtime.XIncref(pyTypeHandle); - Runtime.XIncref(pyValueHandle); - Runtime.XIncref(pyTracebackHandle); + Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); PythonEngine.ReleaseLock(gs); return result; } + /// + /// Rethrows the last Python exception as corresponding CLR exception. + /// It is recommended to call this as throw ThrowLastAsClrException() + /// to assist control flow checks. + /// + internal static Exception ThrowLastAsClrException() { + IntPtr gs = PythonEngine.AcquireLock(); + try { + Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); + var clrObject = ManagedType.GetManagedObject(pyValueHandle) as CLRObject; + if (clrObject?.inst is Exception e) { +#if NETSTANDARD + ExceptionDispatchInfo.Capture(e).Throw(); +#endif + throw e; + } + var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); + throw result; + } finally { + PythonEngine.ReleaseLock(gs); + } + } + /// /// Requires lock to be acquired eslewhere /// - static PythonException FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle) { + static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle) { Exception inner = null; string pythonTypeName = null, msg = "", traceback = null; + + var clrObject = ManagedType.GetManagedObject(pyValueHandle) as CLRObject; + if (clrObject?.inst is Exception e) { + return e; + } + if (pyTypeHandle != IntPtr.Zero && pyValueHandle != IntPtr.Zero) { string type; @@ -126,7 +152,7 @@ static string TracebackHandleToString(IntPtr tracebackHandle) { } PyObject tracebackModule = PythonEngine.ImportModule("traceback"); - PyObject traceback = new PyObject(tracebackHandle); + using var traceback = new PyObject(Runtime.SelfIncRef(tracebackHandle)); PyList stackLines = new PyList(tracebackModule.InvokeMethod("format_tb", traceback)); var result = new StringBuilder(); foreach (object stackLine in stackLines) { diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index bf7c34e78..817123f17 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -452,7 +452,7 @@ internal static void CheckExceptionOccurred() { if (PyErr_Occurred() != IntPtr.Zero) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } } @@ -1665,7 +1665,7 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) internal static IntPtr PyErr_Occurred() => Delegates.PyErr_Occurred(); - internal static void PyErr_Fetch(ref IntPtr ob, ref IntPtr val, ref IntPtr tb) => Delegates.PyErr_Fetch(ref ob, ref val, ref tb); + internal static void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb) => Delegates.PyErr_Fetch(out ob, out val, out tb); internal static void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_Restore(ob, val, tb); @@ -3010,7 +3010,7 @@ int updatepath internal static PyErr_FetchDelegate PyErr_Fetch { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate void PyErr_FetchDelegate(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + internal delegate void PyErr_FetchDelegate(out IntPtr ob, out IntPtr val, out IntPtr tb); internal static PyErr_RestoreDelegate PyErr_Restore { get; } diff --git a/src/runtime/slots.cs b/src/runtime/slots.cs index a252ee269..73bb9d01a 100644 --- a/src/runtime/slots.cs +++ b/src/runtime/slots.cs @@ -84,7 +84,7 @@ public static bool GenericGetAttr(PyObject self, string name, out PyObject resul if (pyResult == IntPtr.Zero) { result = null; if (!PythonException.Matches(Exceptions.AttributeError)) { - throw PythonException.FromPyErr(); + throw PythonException.ThrowLastAsClrException(); } Exceptions.Clear(); From b99ffe5c8adc5ad94b84aa228b082553359fb366 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 24 Feb 2020 17:22:28 -0800 Subject: [PATCH 100/240] allows codecs to encode and decode thrown exceptions --- src/embed_tests/Codecs.cs | 53 +++++++++++++++++++ .../Python.EmbeddingTest.15.csproj | 2 +- src/runtime/exceptions.cs | 2 +- src/runtime/pythonexception.cs | 5 ++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index a3db1dc5e..15447a3fb 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -82,5 +82,58 @@ static void TupleRoundtripGeneric() { Assert.AreEqual(expected: tuple, actual: restored); } } + + const string TestExceptionMessage = "Hello World!"; + [Test] + public void ExceptionEncoded() { + PyObjectConversions.RegisterEncoder(new ValueErrorCodec()); + void CallMe() => throw new ValueErrorWrapper(TestExceptionMessage); + var callMeAction = new Action(CallMe); + using var _ = Py.GIL(); + using var scope = Py.CreateScope(); + scope.Exec(@" +def call(func): + try: + func() + except ValueError as e: + return str(e) +"); + var callFunc = scope.Get("call"); + string message = callFunc.Invoke(callMeAction.ToPython()).As(); + Assert.AreEqual(TestExceptionMessage, message); + } + + [Test] + public void ExceptionDecoded() { + PyObjectConversions.RegisterDecoder(new ValueErrorCodec()); + using var _ = Py.GIL(); + using var scope = Py.CreateScope(); + var error = Assert.Throws(() => PythonEngine.Exec( + $"raise ValueError('{TestExceptionMessage}')")); + Assert.AreEqual(TestExceptionMessage, error.Message); + } + + class ValueErrorWrapper : Exception { + public ValueErrorWrapper(string message) : base(message) { } + } + + class ValueErrorCodec : IPyObjectEncoder, IPyObjectDecoder { + public bool CanDecode(PyObject objectType, Type targetType) + => this.CanEncode(targetType) && objectType.Equals(PythonEngine.Eval("ValueError")); + + public bool CanEncode(Type type) => type == typeof(ValueErrorWrapper) + || typeof(ValueErrorWrapper).IsSubclassOf(type); + + public bool TryDecode(PyObject pyObj, out T value) { + var message = pyObj.GetAttr("args")[0].As(); + value = (T)(object)new ValueErrorWrapper(message); + return true; + } + + public PyObject TryEncode(object value) { + var error = (ValueErrorWrapper)value; + return PythonEngine.Eval("ValueError").Invoke(error.Message.ToPython()); + } + } } } diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index 682cfbe84..d8bf1946b 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -22,7 +22,7 @@ ..\..\ $(SolutionDir)\bin\ $(OutputPath)\$(TargetFramework)_publish - 7.3 + 8.0 prompt $(PYTHONNET_DEFINE_CONSTANTS) XPLAT diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 65126a000..c24340d25 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -265,7 +265,7 @@ public static void SetError(Exception e) return; } - IntPtr op = CLRObject.GetInstHandle(e); + IntPtr op = Converter.ToPython(e); IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__"); Runtime.PyErr_SetObject(etype, op); Runtime.XDecref(etype); diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index f88e9d5fc..c6a966b5e 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -112,6 +112,11 @@ static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyT if (pyTypeHandle != IntPtr.Zero && pyValueHandle != IntPtr.Zero) { + if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), + out object decoded) && decoded is Exception decodedException) { + return decodedException; + } + string type; string message; Runtime.XIncref(pyTypeHandle); From b5061d4ad3541cee1a806fb5ecf0e897663f4e6b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 24 Feb 2020 19:46:41 -0800 Subject: [PATCH 101/240] include symbols into NuGet package --- src/runtime/Python.Runtime.15.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 6d45d4a21..4890f728c 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -7,6 +7,8 @@ Python.Runtime.UnofficialNetStandard 3.0.0 true + true + snupkg false false false From dfd55b9c09fa3565c79b1d2c3b8ad0865a433870 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 3 Mar 2020 13:34:39 -0800 Subject: [PATCH 102/240] fixed ref counting for base types tuple --- src/embed_tests/CallableObject.cs | 2 +- src/runtime/BaseTypeAttributeBase.cs | 4 ++-- src/runtime/interop.cs | 3 ++- src/runtime/pytuple.cs | 7 +++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index 9df5f49d0..2915f9dad 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -64,7 +64,7 @@ class CustomBaseTypeAttribute : BaseTypeAttributeBase { public override PyTuple BaseTypes(Type type) { return type != typeof(CallViaInheritance) ? base.BaseTypes(type) - : PyTuple.FromSingleElement(BaseClass.Handle); + : PyTuple.FromSingleElement(BaseClass); } } } diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs index e3bb6d2c3..549623dc0 100644 --- a/src/runtime/BaseTypeAttributeBase.cs +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -19,12 +19,12 @@ public virtual PyTuple BaseTypes(Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); if (type == typeof(Exception)) { - return PyTuple.FromSingleElement(Exceptions.Exception); + return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(Exceptions.Exception))); } if (type.BaseType != null) { ClassBase bc = ClassManager.GetClass(type.BaseType); - return PyTuple.FromSingleElement(bc.pyHandle); + return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(bc.pyHandle))); } return new PyTuple(); diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index e11b94d58..854c32be4 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -98,7 +98,8 @@ public static int magic(IntPtr ob) } IntPtr tp = Runtime.PyObject_TYPE(ob); - if (Runtime.PyObject_TYPE(tp) == Runtime.PyCLRMetaType) { + IntPtr metatype = Runtime.PyObject_TYPE(tp); + if (metatype == Runtime.PyCLRMetaType) { int offset = (int)Marshal.ReadIntPtr(tp, TypeOffset.clr_gchandle_offset); ClrGcHandleOffsetAssertSanity(offset); return offset; diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 2e583c689..e730d58c6 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -122,7 +122,10 @@ public static PyTuple AsTuple(PyObject value) return new PyTuple(op); } - internal static PyTuple FromSingleElement(IntPtr value) - => new PyTuple(items: new []{new PyObject(value)}); + /// + /// Create a with single element + /// + public static PyTuple FromSingleElement(PyObject value) + => new PyTuple(items: new []{value}); } } From 81764ebd450ea22b91be4e3176f4748befa0edec Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 3 Mar 2020 13:35:19 -0800 Subject: [PATCH 103/240] do not attempt to dispose left over objects from previous runs --- src/runtime/pyobject.cs | 6 ++++-- src/runtime/runtime.cs | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 8ebc962ff..7daeac7f5 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -27,8 +27,9 @@ public class PyObject : DynamicObject, IEnumerable, IPyDisposable /// Trace stack for PyObject's construction /// public StackTrace Traceback { get; private set; } -#endif +#endif + readonly long run = Runtime.GetRun(); protected internal IntPtr obj = IntPtr.Zero; private bool disposed = false; private bool _finalized = false; @@ -181,8 +182,9 @@ protected virtual void Dispose(bool disposing) { if (!disposed) { - if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing) + if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing && this.run == Runtime.GetRun()) { + Debug.Assert(this.run == Runtime.GetRun(), "Attempt to dispose PyObject from wrong run"); IntPtr gs = PythonEngine.AcquireLock(); Runtime.XDecref(obj); obj = IntPtr.Zero; diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index a1a4f3680..852bb6276 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -192,6 +192,14 @@ static int GetPyVersionNumber() { private static PyReferenceCollection _pyRefs = new PyReferenceCollection(); + static long run = 0; + + internal static long GetRun() { + long runNumber = Interlocked.Read(ref run); + System.Diagnostics.Debug.Assert(runNumber > 0); + return runNumber; + } + /// /// Initialize the runtime... /// @@ -309,6 +317,8 @@ internal static void Initialize(bool initSigs = false) Error = new IntPtr(-1); + Interlocked.Increment(ref run); + // Initialize data about the platform we're running on. We need // this for the type manager and potentially other details. Must // happen after caching the python types, above. From 178db0e44fc0b254b644cbb4749469c58c91cca1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 6 Mar 2020 22:26:45 -0800 Subject: [PATCH 104/240] fixed primitive wrapper constructors to check for exceptions only on failure --- src/runtime/pyansistring.cs | 2 +- src/runtime/pyfloat.cs | 2 +- src/runtime/pyint.cs | 10 +++++----- src/runtime/pythonexception.cs | 4 +++- src/runtime/pytuple.cs | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs index a9cae0a8a..acedc59c6 100644 --- a/src/runtime/pyansistring.cs +++ b/src/runtime/pyansistring.cs @@ -48,7 +48,7 @@ static IntPtr FromPyObject(PyObject o) /// /// Creates a Python string from a managed string. /// - public PyAnsiString(string s):base(Exceptions.ErrorOccurredCheck(Runtime.PyString_FromString(s))) + public PyAnsiString(string s):base(PythonException.ThrowIfIsNull(Runtime.PyString_FromString(s))) { } diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs index d584feb7d..3a5f92e3c 100644 --- a/src/runtime/pyfloat.cs +++ b/src/runtime/pyfloat.cs @@ -53,7 +53,7 @@ static IntPtr FromPyObject(PyObject o) /// /// Creates a new Python float from a double value. /// - public PyFloat(double value):base(Exceptions.ErrorOccurredCheck(Runtime.PyFloat_FromDouble(value))) + public PyFloat(double value):base(PythonException.ThrowIfIsNull(Runtime.PyFloat_FromDouble(value))) { } diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs index f367d922e..9ed41cdd7 100644 --- a/src/runtime/pyint.cs +++ b/src/runtime/pyint.cs @@ -54,7 +54,7 @@ static IntPtr FromPyObject(PyObject o) /// /// Creates a new Python int from an int32 value. /// - public PyInt(int value):base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt32(value))) + public PyInt(int value):base(PythonException.ThrowIfIsNull(Runtime.PyInt_FromInt32(value))) { } @@ -66,7 +66,7 @@ public PyInt(int value):base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt /// Creates a new Python int from a uint32 value. /// [CLSCompliant(false)] - public PyInt(uint value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64(value))) + public PyInt(uint value) : base(PythonException.ThrowIfIsNull(Runtime.PyInt_FromInt64(value))) { } @@ -77,7 +77,7 @@ public PyInt(uint value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_From /// /// Creates a new Python int from an int64 value. /// - public PyInt(long value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64(value))) + public PyInt(long value) : base(PythonException.ThrowIfIsNull(Runtime.PyInt_FromInt64(value))) { } @@ -89,7 +89,7 @@ public PyInt(long value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_From /// Creates a new Python int from a uint64 value. /// [CLSCompliant(false)] - public PyInt(ulong value) : base(Exceptions.ErrorOccurredCheck(Runtime.PyInt_FromInt64((long)value))) + public PyInt(ulong value) : base(PythonException.ThrowIfIsNull(Runtime.PyInt_FromInt64((long)value))) { } @@ -147,7 +147,7 @@ public PyInt(sbyte value) : this((int)value) /// Creates a new Python int from a string value. /// public PyInt(string value):base( - Exceptions.ErrorOccurredCheck( + PythonException.ThrowIfIsNull( Runtime.PyInt_FromString(value ?? throw new ArgumentNullException(nameof(value)), IntPtr.Zero, 0))) { } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 859511332..f22c61d16 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -311,12 +311,14 @@ public static bool Matches(IntPtr ob) return Runtime.PyErr_ExceptionMatches(ob) != 0; } - public static void ThrowIfIsNull(IntPtr ob) + public static IntPtr ThrowIfIsNull(IntPtr ob) { if (ob == IntPtr.Zero) { throw PythonException.ThrowLastAsClrException(); } + + return ob; } public static void ThrowIfIsNotZero(int value) diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index e730d58c6..9a6ebb6cf 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -53,7 +53,7 @@ static IntPtr FromPyObject(PyObject o) /// /// Creates a new empty PyTuple. /// - public PyTuple():base(Exceptions.ErrorOccurredCheck(Runtime.PyTuple_New(0))) + public PyTuple():base(PythonException.ThrowIfIsNull(Runtime.PyTuple_New(0))) { } From 3187c068118741699d1b44254a60b70fe8f047b5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 6 Mar 2020 22:30:14 -0800 Subject: [PATCH 105/240] add Python cause (if any) to InvalidCastException in PyObject.As --- src/runtime/pyobject.cs | 6 ++++-- src/runtime/pythonexception.cs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 7daeac7f5..6c3ac119f 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -140,7 +140,8 @@ public object AsManagedObject(Type t) object result; if (!Converter.ToManaged(obj, t, out result, false)) { - throw new InvalidCastException("cannot convert object to target type"); + throw new InvalidCastException("cannot convert object to target type", + innerException: PythonException.FromPyErrOrNull()); } return result; } @@ -161,7 +162,8 @@ public T As() object result; if (!Converter.ToManaged(obj, typeof(T), out result, false)) { - throw new InvalidCastException("cannot convert object to target type"); + throw new InvalidCastException("cannot convert object to target type", + innerException: PythonException.FromPyErrOrNull()); } return (T)result; } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index f22c61d16..9988672e2 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -73,6 +73,19 @@ internal static Exception FromPyErr() { return result; } + internal static Exception FromPyErrOrNull() + { + IntPtr gs = PythonEngine.AcquireLock(); + Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); + if (pyValueHandle == IntPtr.Zero && pyTypeHandle == IntPtr.Zero && pyTracebackHandle == IntPtr.Zero) + { + return null; + } + var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); + PythonEngine.ReleaseLock(gs); + return result; + } + /// /// Rethrows the last Python exception as corresponding CLR exception. /// It is recommended to call this as throw ThrowLastAsClrException() From e263a9edebfc11ef798f85ec62dc23f80414eeb8 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 6 Mar 2020 22:30:54 -0800 Subject: [PATCH 106/240] fixed tuple codec not clearing Python exception after unsuccessful element decoding attempt --- src/runtime/Codecs/TupleCodecs.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs index 4c81cac0b..a9ae33fe0 100644 --- a/src/runtime/Codecs/TupleCodecs.cs +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -81,6 +81,7 @@ public bool TryDecode(PyObject pyObj, out T value) IntPtr pyItem = Runtime.PyTuple_GetItem(pyObj.Handle, itemIndex); if (!Converter.ToManaged(pyItem, itemTypes[itemIndex], out elements[itemIndex], setError: false)) { + Exceptions.Clear(); return false; } } @@ -105,6 +106,7 @@ static bool Decode(PyObject tuple, out object value) var pyItem = Runtime.PyTuple_GetItem(tuple.Handle, itemIndex); if (!Converter.ToManaged(pyItem, typeof(object), out elements[itemIndex], setError: false)) { + Exceptions.Clear(); return false; } From d91c12f28dd324f21bcf0cfd6ebdcbe94464aab7 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 9 Mar 2020 21:47:24 -0700 Subject: [PATCH 107/240] added Codecs: EncoderGroup and DecoderGroup These classes would help to manage codec layers. For example, a library could register its own codecs, but also allow anyone to inject their codecs before library's own: public static EncoderGroup BeforeLibraryEncoders { get; } = new EncoderGroup(); void LibraryRegisterCodecs(){ PyObjectConversions.RegisterEncoder(BeforeLibraryEncoders); PyObjectConversions.RegisterEncoder(LibraryEncoder.Instance); } Then in a program using that library: Library.BeforeLibraryEncoders.Encoders.Add(preencoder); --- src/embed_tests/CodecGroups.cs | 132 ++++++++++++++++++++ src/embed_tests/Codecs.cs | 58 +++++++++ src/embed_tests/Python.EmbeddingTest.csproj | 1 + src/runtime/Codecs/DecoderGroup.cs | 78 ++++++++++++ src/runtime/Codecs/EncoderGroup.cs | 79 ++++++++++++ src/runtime/Python.Runtime.csproj | 2 + src/runtime/converterextensions.cs | 17 +-- 7 files changed, 359 insertions(+), 8 deletions(-) create mode 100644 src/embed_tests/CodecGroups.cs create mode 100644 src/runtime/Codecs/DecoderGroup.cs create mode 100644 src/runtime/Codecs/EncoderGroup.cs diff --git a/src/embed_tests/CodecGroups.cs b/src/embed_tests/CodecGroups.cs new file mode 100644 index 000000000..a661c5323 --- /dev/null +++ b/src/embed_tests/CodecGroups.cs @@ -0,0 +1,132 @@ +namespace Python.EmbeddingTest +{ + using System; + using System.Linq; + using NUnit.Framework; + using Python.Runtime; + using Python.Runtime.Codecs; + + public class CodecGroups + { + [Test] + public void GetEncodersByType() + { + var encoder1 = new FakeEncoder(); + var encoder2 = new FakeEncoder(); + var group = new EncoderGroup { + new FakeEncoder>(), + encoder1, + encoder2, + }; + + var got = group.GetEncoders(typeof(Uri)).ToArray(); + CollectionAssert.AreEqual(new[]{encoder1, encoder2}, got); + } + + [Test] + public void CanEncode() + { + var group = new EncoderGroup { + new FakeEncoder>(), + new FakeEncoder(), + }; + + Assert.IsTrue(group.CanEncode(typeof(Tuple))); + Assert.IsTrue(group.CanEncode(typeof(Uri))); + Assert.IsFalse(group.CanEncode(typeof(string))); + } + + [Test] + public void Encodes() + { + var encoder0 = new FakeEncoder>(); + var encoder1 = new FakeEncoder(); + var encoder2 = new FakeEncoder(); + var group = new EncoderGroup { + encoder0, + encoder1, + encoder2, + }; + + var uri = group.TryEncode(new Uri("data:")); + var clrObject = (CLRObject)ManagedType.GetManagedObject(uri.Handle); + Assert.AreSame(encoder1, clrObject.inst); + Assert.AreNotSame(encoder2, clrObject.inst); + + var tuple = group.TryEncode(Tuple.Create(1)); + clrObject = (CLRObject)ManagedType.GetManagedObject(tuple.Handle); + Assert.AreSame(encoder0, clrObject.inst); + } + + [Test] + public void GetDecodersByTypes() + { + var pyint = new PyInt(10).GetPythonType(); + var pyfloat = new PyFloat(10).GetPythonType(); + var pystr = new PyString("world").GetPythonType(); + var decoder1 = new FakeDecoder(pyint, 42); + var decoder2 = new FakeDecoder(pyfloat, "atad:"); + var group = new DecoderGroup { + decoder1, + decoder2, + }; + + var decoder = group.GetDecoder(pyfloat, typeof(string)); + Assert.AreSame(decoder2, decoder); + decoder = group.GetDecoder(pystr, typeof(string)); + Assert.IsNull(decoder); + decoder = group.GetDecoder(pyint, typeof(long)); + Assert.AreSame(decoder1, decoder); + } + [Test] + public void CanDecode() + { + var pyint = new PyInt(10).GetPythonType(); + var pyfloat = new PyFloat(10).GetPythonType(); + var pystr = new PyString("world").GetPythonType(); + var decoder1 = new FakeDecoder(pyint, 42); + var decoder2 = new FakeDecoder(pyfloat, "atad:"); + var group = new DecoderGroup { + decoder1, + decoder2, + }; + + Assert.IsTrue(group.CanDecode(pyint, typeof(long))); + Assert.IsFalse(group.CanDecode(pyint, typeof(int))); + Assert.IsTrue(group.CanDecode(pyfloat, typeof(string))); + Assert.IsFalse(group.CanDecode(pystr, typeof(string))); + } + + [Test] + public void Decodes() + { + var pyint = new PyInt(10).GetPythonType(); + var pyfloat = new PyFloat(10).GetPythonType(); + var decoder1 = new FakeDecoder(pyint, 42); + var decoder2 = new FakeDecoder(pyfloat, "atad:"); + var group = new DecoderGroup { + decoder1, + decoder2, + }; + + Assert.IsTrue(group.TryDecode(new PyInt(10), out long longResult)); + Assert.AreEqual(42, longResult); + Assert.IsTrue(group.TryDecode(new PyFloat(10), out string strResult)); + Assert.AreSame("atad:", strResult); + + Assert.IsFalse(group.TryDecode(new PyInt(10), out int _)); + } + + [SetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [TearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + } +} diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index aaa9905d7..0b4716518 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -136,4 +136,62 @@ public PyObject TryEncode(object value) { } } } + + class FakeEncoder : IPyObjectEncoder + { + public bool CanEncode(Type type) => type == typeof(T); + public PyObject TryEncode(object value) => this.GetRawPythonProxy(); + } + + class FakeDecoder : IPyObjectDecoder + { + public PyObject TheOnlySupportedSourceType { get; } + public TTarget DecodeResult { get; } + + public FakeDecoder(PyObject objectType, TTarget decodeResult) + { + this.TheOnlySupportedSourceType = objectType; + this.DecodeResult = decodeResult; + } + + public bool CanDecode(PyObject objectType, Type targetType) + => objectType.Handle == TheOnlySupportedSourceType.Handle + && targetType == typeof(TTarget); + public bool TryDecode(PyObject pyObj, out T value) + { + if (typeof(T) != typeof(TTarget)) + throw new ArgumentException(nameof(T)); + value = (T)(object)DecodeResult; + return true; + } + } + + class FakeEncoder : IPyObjectEncoder + { + public bool CanEncode(Type type) => type == typeof(T); + public PyObject TryEncode(object value) => this.GetRawPythonProxy(); + } + + class FakeDecoder : IPyObjectDecoder + { + public PyObject TheOnlySupportedSourceType { get; } + public TTarget DecodeResult { get; } + + public FakeDecoder(PyObject objectType, TTarget decodeResult) + { + this.TheOnlySupportedSourceType = objectType; + this.DecodeResult = decodeResult; + } + + public bool CanDecode(PyObject objectType, Type targetType) + => objectType.Handle == TheOnlySupportedSourceType.Handle + && targetType == typeof(TTarget); + public bool TryDecode(PyObject pyObj, out T value) + { + if (typeof(T) != typeof(TTarget)) + throw new ArgumentException(nameof(T)); + value = (T)(object)DecodeResult; + return true; + } + } } diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 9c5f97711..5dee66e64 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -83,6 +83,7 @@ + diff --git a/src/runtime/Codecs/DecoderGroup.cs b/src/runtime/Codecs/DecoderGroup.cs new file mode 100644 index 000000000..8a290d5d4 --- /dev/null +++ b/src/runtime/Codecs/DecoderGroup.cs @@ -0,0 +1,78 @@ +namespace Python.Runtime.Codecs +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + + /// + /// Represents a group of s. Useful to group them by priority. + /// + [Obsolete(Util.UnstableApiMessage)] + public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable + { + readonly List decoders = new List(); + + /// + /// Add specified decoder to the group + /// + public void Add(IPyObjectDecoder item) + { + if (item is null) throw new ArgumentNullException(nameof(item)); + + this.decoders.Add(item); + } + /// + /// Remove all decoders from the group + /// + public void Clear() => this.decoders.Clear(); + + /// + public bool CanDecode(PyObject objectType, Type targetType) + => this.decoders.Any(decoder => decoder.CanDecode(objectType, targetType)); + /// + public bool TryDecode(PyObject pyObj, out T value) + { + if (pyObj is null) throw new ArgumentNullException(nameof(pyObj)); + + var decoder = this.GetDecoder(pyObj.GetPythonType(), typeof(T)); + if (decoder is null) + { + value = default; + return false; + } + return decoder.TryDecode(pyObj, out value); + } + + /// + public IEnumerator GetEnumerator() => this.decoders.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => this.decoders.GetEnumerator(); + } + + [Obsolete(Util.UnstableApiMessage)] + public static class DecoderGroupExtensions + { + /// + /// Gets a concrete instance of + /// (potentially selecting one from a collection), + /// that can decode from to , + /// or null if a matching decoder can not be found. + /// + [Obsolete(Util.UnstableApiMessage)] + public static IPyObjectDecoder GetDecoder( + this IPyObjectDecoder decoder, + PyObject objectType, Type targetType) + { + if (decoder is null) throw new ArgumentNullException(nameof(decoder)); + + if (decoder is IEnumerable composite) + { + return composite + .Select(nestedDecoder => nestedDecoder.GetDecoder(objectType, targetType)) + .FirstOrDefault(d => d != null); + } + + return decoder.CanDecode(objectType, targetType) ? decoder : null; + } + } +} diff --git a/src/runtime/Codecs/EncoderGroup.cs b/src/runtime/Codecs/EncoderGroup.cs new file mode 100644 index 000000000..a5708c0bb --- /dev/null +++ b/src/runtime/Codecs/EncoderGroup.cs @@ -0,0 +1,79 @@ +namespace Python.Runtime.Codecs +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + + /// + /// Represents a group of s. Useful to group them by priority. + /// + [Obsolete(Util.UnstableApiMessage)] + public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable + { + readonly List encoders = new List(); + + /// + /// Add specified encoder to the group + /// + public void Add(IPyObjectEncoder item) + { + if (item is null) throw new ArgumentNullException(nameof(item)); + this.encoders.Add(item); + } + /// + /// Remove all encoders from the group + /// + public void Clear() => this.encoders.Clear(); + + /// + public bool CanEncode(Type type) => this.encoders.Any(encoder => encoder.CanEncode(type)); + /// + public PyObject TryEncode(object value) + { + if (value is null) throw new ArgumentNullException(nameof(value)); + + foreach (var encoder in this.GetEncoders(value.GetType())) + { + var result = encoder.TryEncode(value); + if (result != null) + { + return result; + } + } + + return null; + } + + /// + public IEnumerator GetEnumerator() => this.encoders.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => this.encoders.GetEnumerator(); + } + + [Obsolete(Util.UnstableApiMessage)] + public static class EncoderGroupExtensions + { + /// + /// Gets specific instances of + /// (potentially selecting one from a collection), + /// that can encode the specified . + /// + [Obsolete(Util.UnstableApiMessage)] + public static IEnumerable GetEncoders(this IPyObjectEncoder decoder, Type type) + { + if (decoder is null) throw new ArgumentNullException(nameof(decoder)); + + if (decoder is IEnumerable composite) + { + foreach (var nestedEncoder in composite) + foreach (var match in nestedEncoder.GetEncoders(type)) + { + yield return match; + } + } else if (decoder.CanEncode(type)) + { + yield return decoder; + } + } + } +} diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index fd2d35bde..0a4359796 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -76,6 +76,8 @@ + + diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index fd012c6e4..d8806ca30 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -5,6 +5,7 @@ namespace Python.Runtime using System.Collections.Generic; using System.Linq; using System.Reflection; + using Python.Runtime.Codecs; /// /// Defines conversion to CLR types (unmarshalling) @@ -49,8 +50,8 @@ public interface IPyObjectEncoder [Obsolete(Util.UnstableApiMessage)] public static class PyObjectConversions { - static readonly List decoders = new List(); - static readonly List encoders = new List(); + static readonly DecoderGroup decoders = new DecoderGroup(); + static readonly EncoderGroup encoders = new EncoderGroup(); /// /// Registers specified encoder (marshaller) @@ -62,7 +63,7 @@ public static void RegisterEncoder(IPyObjectEncoder encoder) lock (encoders) { - encoders.Add(encoder); + encoders.Encoders.Add(encoder); } } @@ -76,7 +77,7 @@ public static void RegisterDecoder(IPyObjectDecoder decoder) lock (decoders) { - decoders.Add(decoder); + decoders.Decoders.Add(decoder); } } @@ -101,7 +102,7 @@ static IPyObjectEncoder[] GetEncoders(Type type) { lock (encoders) { - return encoders.Where(encoder => encoder.CanEncode(type)).ToArray(); + return encoders.GetEncoders(type).ToArray(); } } #endregion @@ -128,7 +129,7 @@ static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type { lock (decoders) { - decoder = decoders.Find(d => d.CanDecode(pyType, targetType)); + decoder = decoders.GetDecoder(pyType, targetType); if (decoder == null) return null; } } @@ -163,8 +164,8 @@ internal static void Reset() { clrToPython.Clear(); pythonToClr.Clear(); - encoders.Clear(); - decoders.Clear(); + encoders.Encoders.Clear(); + decoders.Decoders.Clear(); } } From 3b2d7e1dbdea1f232b3fdfa10f8c61b89e04ebcd Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 13 Mar 2020 19:11:30 -0700 Subject: [PATCH 108/240] fixed custom Python DLL loading on Linux and Mac --- src/runtime/Platforms/LinuxLibraryLoader.cs | 3 ++- src/runtime/Platforms/MacLibraryLoader.cs | 3 ++- src/runtime/platform/LibraryLoader.cs | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/runtime/Platforms/LinuxLibraryLoader.cs b/src/runtime/Platforms/LinuxLibraryLoader.cs index 0957c6eb9..1f7aea1ff 100644 --- a/src/runtime/Platforms/LinuxLibraryLoader.cs +++ b/src/runtime/Platforms/LinuxLibraryLoader.cs @@ -1,5 +1,6 @@ namespace Python.Runtime.Platforms { using System; + using System.IO; using System.Runtime.InteropServices; sealed class LinuxLibraryLoader: UnixLibraryLoader { @@ -8,7 +9,7 @@ sealed class LinuxLibraryLoader: UnixLibraryLoader { const int RTLD_GLOBAL = 0x100; const string LinuxNativeDll = "libdl.so"; public override IntPtr LoadLibrary(string path) { - path = string.IsNullOrEmpty(System.IO.Path.GetExtension(path)) ? $"lib{path}.so" : path; + path = File.Exists(path) ? path : $"lib{path}.so"; return Linux.dlopen(path, RTLD_NOW | RTLD_GLOBAL); } diff --git a/src/runtime/Platforms/MacLibraryLoader.cs b/src/runtime/Platforms/MacLibraryLoader.cs index 130e277cb..dc1dce90d 100644 --- a/src/runtime/Platforms/MacLibraryLoader.cs +++ b/src/runtime/Platforms/MacLibraryLoader.cs @@ -1,12 +1,13 @@ namespace Python.Runtime.Platforms { using System; + using System.IO; using System.Runtime.InteropServices; class MacLibraryLoader: UnixLibraryLoader { public static MacLibraryLoader Instance { get; } = new MacLibraryLoader(); const int RTLD_GLOBAL = 0x8; public override IntPtr LoadLibrary(string path) { - path = string.IsNullOrEmpty(System.IO.Path.GetExtension(path)) ? $"lib{path}.dylib" : path; + path = File.Exists(path) ? path : $"lib{path}.dylib"; return Mac.dlopen(path, RTLD_NOW | RTLD_GLOBAL); } diff --git a/src/runtime/platform/LibraryLoader.cs b/src/runtime/platform/LibraryLoader.cs index a6d88cd19..4aa6d53a2 100644 --- a/src/runtime/platform/LibraryLoader.cs +++ b/src/runtime/platform/LibraryLoader.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.IO; using System.Runtime.InteropServices; namespace Python.Runtime.Platform @@ -40,7 +41,7 @@ class LinuxLoader : ILibraryLoader public IntPtr Load(string dllToLoad) { - var filename = $"lib{dllToLoad}.so"; + var filename = File.Exists(dllToLoad) ? dllToLoad : $"lib{dllToLoad}.so"; ClearError(); var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (res == IntPtr.Zero) @@ -111,7 +112,7 @@ class DarwinLoader : ILibraryLoader public IntPtr Load(string dllToLoad) { - var filename = $"lib{dllToLoad}.dylib"; + var filename = File.Exists(dllToLoad) ? dllToLoad : $"lib{dllToLoad}.dylib"; ClearError(); var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (res == IntPtr.Zero) From f3362e8fd8db83e7024f6838bcdc02a2069e467d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 13 Mar 2020 19:17:37 -0700 Subject: [PATCH 109/240] fixed merge artifacts --- src/embed_tests/Codecs.cs | 29 ----------------------------- src/runtime/converterextensions.cs | 8 ++++---- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 0b4716518..5dd02ecf5 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -165,33 +165,4 @@ public bool TryDecode(PyObject pyObj, out T value) return true; } } - - class FakeEncoder : IPyObjectEncoder - { - public bool CanEncode(Type type) => type == typeof(T); - public PyObject TryEncode(object value) => this.GetRawPythonProxy(); - } - - class FakeDecoder : IPyObjectDecoder - { - public PyObject TheOnlySupportedSourceType { get; } - public TTarget DecodeResult { get; } - - public FakeDecoder(PyObject objectType, TTarget decodeResult) - { - this.TheOnlySupportedSourceType = objectType; - this.DecodeResult = decodeResult; - } - - public bool CanDecode(PyObject objectType, Type targetType) - => objectType.Handle == TheOnlySupportedSourceType.Handle - && targetType == typeof(TTarget); - public bool TryDecode(PyObject pyObj, out T value) - { - if (typeof(T) != typeof(TTarget)) - throw new ArgumentException(nameof(T)); - value = (T)(object)DecodeResult; - return true; - } - } } diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index d8806ca30..667fc6f00 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -63,7 +63,7 @@ public static void RegisterEncoder(IPyObjectEncoder encoder) lock (encoders) { - encoders.Encoders.Add(encoder); + encoders.Add(encoder); } } @@ -77,7 +77,7 @@ public static void RegisterDecoder(IPyObjectDecoder decoder) lock (decoders) { - decoders.Decoders.Add(decoder); + decoders.Add(decoder); } } @@ -164,8 +164,8 @@ internal static void Reset() { clrToPython.Clear(); pythonToClr.Clear(); - encoders.Encoders.Clear(); - decoders.Decoders.Clear(); + encoders.Clear(); + decoders.Clear(); } } From 80575ad23b0551b572dadee143604065d425a33a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 13 Mar 2020 23:58:02 -0700 Subject: [PATCH 110/240] fixed Python exception stack being printed in wrong order --- src/runtime/pythonexception.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 9988672e2..31ec4be9f 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -170,6 +170,7 @@ static string TracebackHandleToString(IntPtr tracebackHandle) { PyObject tracebackModule = PythonEngine.ImportModule("traceback"); using var traceback = new PyObject(Runtime.SelfIncRef(tracebackHandle)); PyList stackLines = new PyList(tracebackModule.InvokeMethod("format_tb", traceback)); + stackLines.Reverse(); var result = new StringBuilder(); foreach (object stackLine in stackLines) { result.Append(stackLine); From 474af2b587d4856751b9aa0aad772b5248cf54c2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 16 Mar 2020 14:31:46 -0700 Subject: [PATCH 111/240] typo --- src/runtime/pythonexception.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 31ec4be9f..1ce4a7387 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -110,7 +110,7 @@ internal static Exception ThrowLastAsClrException() { } /// - /// Requires lock to be acquired eslewhere + /// Requires lock to be acquired elsewhere /// static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle) { Exception inner = null; From 5ae10e7f60ff20ab5d7036691a2d8bb7beba8fd4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 12:24:31 -0700 Subject: [PATCH 112/240] simplified Finalizer This is an attempt to make finalizer much simpler. Instead of using .NET async tasks, Py_AddPendingCall or other synchronization mechanism we simply move objects to be finalized into a ConcurrentQueue, which is periodically drained when a new PyObject is constructed. --- CHANGELOG.md | 1 + src/embed_tests/TestFinalizer.cs | 2 +- src/runtime/finalizer.cs | 106 ++++++++++--------------------- src/runtime/pyobject.cs | 24 +++---- src/runtime/pythonengine.cs | 1 + 5 files changed, 46 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db126bd1c..51bf456fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Changed usage of obselete function GetDelegateForFunctionPointer(IntPtr, Type) to GetDelegateForFunctionPointer(IntPtr) - When calling C# from Python, enable passing argument of any type to a parameter of C# type `object` by wrapping it into `PyObject` instance. ([#881][i881]) - Added support for kwarg parameters when calling .NET methods from Python +- Reworked `Finalizer`. Now objects drop into its queue upon finalization, which is periodically drained when new objects are created. ### Fixed diff --git a/src/embed_tests/TestFinalizer.cs b/src/embed_tests/TestFinalizer.cs index 650ee5686..f82767af1 100644 --- a/src/embed_tests/TestFinalizer.cs +++ b/src/embed_tests/TestFinalizer.cs @@ -77,7 +77,7 @@ public void CollectBasicObject() } try { - Finalizer.Instance.Collect(forceDispose: false); + Finalizer.Instance.Collect(); } finally { diff --git a/src/runtime/finalizer.cs b/src/runtime/finalizer.cs index dd5c0b4dd..e16315296 100644 --- a/src/runtime/finalizer.cs +++ b/src/runtime/finalizer.cs @@ -25,12 +25,10 @@ public class ErrorArgs : EventArgs public event EventHandler ErrorHandler; public int Threshold { get; set; } + [Obsolete("Finalizer will always be enabled in the future")] public bool Enable { get; set; } private ConcurrentQueue _objQueue = new ConcurrentQueue(); - private bool _pending = false; - private readonly object _collectingLock = new object(); - private Task _finalizerTask; #region FINALIZER_CHECK @@ -75,19 +73,17 @@ private Finalizer() Threshold = 200; } - public void Collect(bool forceDispose = true) + [Obsolete("forceDispose parameter is unused. All objects are disposed regardless.")] + public void Collect(bool forceDispose) => this.DisposeAll(); + public void Collect() => this.DisposeAll(); + + int _throttled; + internal void ThrottledCollect() { - if (Instance._finalizerTask != null - && !Instance._finalizerTask.IsCompleted) - { - var ts = PythonEngine.BeginAllowThreads(); - Instance._finalizerTask.Wait(); - PythonEngine.EndAllowThreads(ts); - } - else if (forceDispose) - { - Instance.DisposeAll(); - } + _throttled = unchecked(this._throttled + 1); + if (!Enable || _throttled < Threshold) return; + _throttled = 0; + this.Collect(); } public List GetCollectedObjects() @@ -97,66 +93,15 @@ public List GetCollectedObjects() internal void AddFinalizedObject(IPyDisposable obj) { - if (!Enable) - { - return; - } - if (Runtime.Py_IsInitialized() == 0) - { - // XXX: Memory will leak if a PyObject finalized after Python shutdown, - // for avoiding that case, user should call GC.Collect manual before shutdown. - return; - } -#if FINALIZER_CHECK - lock (_queueLock) -#endif + if (Enable) { - _objQueue.Enqueue(obj); - } - GC.ReRegisterForFinalize(obj); - if (!_pending && _objQueue.Count >= Threshold) - { - AddPendingCollect(); + this._objQueue.Enqueue(obj); } } internal static void Shutdown() { - if (Runtime.Py_IsInitialized() == 0) - { - Instance._objQueue = new ConcurrentQueue(); - return; - } - Instance.Collect(forceDispose: true); - } - - private void AddPendingCollect() - { - if(Monitor.TryEnter(_collectingLock)) - { - try - { - if (!_pending) - { - _pending = true; - // should already be complete but just in case - _finalizerTask?.Wait(); - - _finalizerTask = Task.Factory.StartNew(() => - { - using (Py.GIL()) - { - Instance.DisposeAll(); - _pending = false; - } - }); - } - } - finally - { - Monitor.Exit(_collectingLock); - } - } + Instance.DisposeAll(); } private void DisposeAll() @@ -178,12 +123,18 @@ private void DisposeAll() try { obj.Dispose(); - Runtime.CheckExceptionOccurred(); } catch (Exception e) { - // We should not bother the main thread - ErrorHandler?.Invoke(this, new ErrorArgs() + var handler = ErrorHandler; + if (handler is null) + { + throw new FinalizationException( + "Python object finalization failed", + disposable: obj, innerException: e); + } + + handler.Invoke(this, new ErrorArgs() { Error = e }); @@ -267,4 +218,15 @@ private void ValidateRefCount() } #endif } + + public class FinalizationException : Exception + { + public IPyDisposable Disposable { get; } + + public FinalizationException(string message, IPyDisposable disposable, Exception innerException) + : base(message, innerException) + { + this.Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable)); + } + } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 6c3ac119f..184057450 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -31,8 +31,6 @@ public class PyObject : DynamicObject, IEnumerable, IPyDisposable readonly long run = Runtime.GetRun(); protected internal IntPtr obj = IntPtr.Zero; - private bool disposed = false; - private bool _finalized = false; internal BorrowedReference Reference => new BorrowedReference(obj); @@ -50,6 +48,7 @@ public PyObject(IntPtr ptr) if (ptr == IntPtr.Zero) throw new ArgumentNullException(nameof(ptr)); obj = ptr; + Finalizer.Instance.ThrottledCollect(); #if TRACE_ALLOC Traceback = new StackTrace(1); #endif @@ -65,6 +64,7 @@ internal PyObject(BorrowedReference reference) if (reference.IsNull) throw new ArgumentNullException(nameof(reference)); obj = Runtime.SelfIncRef(reference.DangerousGetAddress()); + Finalizer.Instance.ThrottledCollect(); #if TRACE_ALLOC Traceback = new StackTrace(1); #endif @@ -75,6 +75,7 @@ internal PyObject(BorrowedReference reference) [Obsolete("Please, always use PyObject(*Reference)")] protected PyObject() { + Finalizer.Instance.ThrottledCollect(); #if TRACE_ALLOC Traceback = new StackTrace(1); #endif @@ -88,12 +89,6 @@ protected PyObject() { return; } - if (_finalized || disposed) - { - return; - } - // Prevent a infinity loop by calling GC.WaitForPendingFinalizers - _finalized = true; Finalizer.Instance.AddFinalizedObject(this); } @@ -182,17 +177,16 @@ public T As() /// protected virtual void Dispose(bool disposing) { - if (!disposed) + if (this.obj != IntPtr.Zero) { - if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing && this.run == Runtime.GetRun()) + if (Runtime.Py_IsInitialized() == 0) + throw new InvalidOperationException("Python runtime must be initialized"); + + if (!Runtime.IsFinalizing) { - Debug.Assert(this.run == Runtime.GetRun(), "Attempt to dispose PyObject from wrong run"); - IntPtr gs = PythonEngine.AcquireLock(); Runtime.XDecref(obj); - obj = IntPtr.Zero; - PythonEngine.ReleaseLock(gs); } - disposed = true; + obj = IntPtr.Zero; } } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index a57d64e2b..ba304d632 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -80,6 +80,7 @@ public static string PythonHome } set { + // this value is null in the beginning Marshal.FreeHGlobal(_pythonHome); _pythonHome = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); Runtime.Py_SetPythonHome(_pythonHome); From 9077f836b56c621ee3b15203d3482fee2dfe9528 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 20:57:10 -0700 Subject: [PATCH 113/240] fixed cached reference to inspect module stayed after shutdown --- src/runtime/runtime.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 852bb6276..893160a71 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -353,6 +353,8 @@ internal static void Initialize(bool initSigs = false) PyList_Append(new BorrowedReference(path), item); XDecref(item); AssemblyManager.UpdatePath(); + + inspect = GetInspectModuleLazy(); } /// @@ -414,6 +416,9 @@ internal static void Shutdown() Py_Finalize(); } + private static Lazy GetInspectModuleLazy() + => new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); + // called *without* the GIL acquired by clr._AtExit internal static int AtExit() { @@ -480,8 +485,7 @@ private static void ResetPyMembers() internal static IntPtr PyNone; internal static IntPtr Error; - private static readonly Lazy inspect = - new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); + private static Lazy inspect; public static PyObject InspectModule => inspect.Value; /// From 85d74d79921c2b26971884010a1a7f8b4a53484d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:10:11 -0700 Subject: [PATCH 114/240] use BorrowedReference in TryDecode --- src/runtime/converter.cs | 27 +++++++++++++++------------ src/runtime/converterextensions.cs | 14 +++++++------- src/runtime/pytuple.cs | 3 +-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 8dc6bc486..c5c52c5c4 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -392,8 +392,8 @@ internal static bool ToManagedValue(IntPtr value, Type obType, } // give custom codecs a chance to take over conversion of sequences - IntPtr pyType = Runtime.PyObject_TYPE(value); - if (PyObjectConversions.TryDecode(value, pyType, obType, out result)) + var pyType = new BorrowedReference(Runtime.PyObject_TYPE(value)); + if (PyObjectConversions.TryDecode(new BorrowedReference(value), pyType, obType, out result)) { return true; } @@ -459,13 +459,13 @@ internal static bool ToManagedValue(IntPtr value, Type obType, if (typeCode == TypeCode.Object) { var converter = TypeConverterCache.GetOrAdd(obType, GetConverter); - if (converter != null && converter(value, out result)) + if (converter != null && converter(new BorrowedReference(value), out result)) { return true; } - IntPtr pyType = Runtime.PyObject_TYPE(value); - if (PyObjectConversions.TryDecode(value, pyType, obType, out result)) + var pyType = new BorrowedReference(Runtime.PyObject_TYPE(value)); + if (PyObjectConversions.TryDecode(new BorrowedReference(value), pyType, obType, out result)) { return true; } @@ -496,19 +496,22 @@ static TryConvertFromPythonDelegate GetConverter(Type targetType) } convert = convert.MakeGenericMethod(targetType); - bool TryConvert(IntPtr pyHandle, out object result) { - using (var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle))) { - var @params = new object[] {pyObj, null}; - bool success = (bool)convert.Invoke(converterAttribute, @params); - result = @params[1]; - return success; + bool TryConvert(BorrowedReference pyHandle, out object result) { + var pyObj = new PyObject(pyHandle); + var @params = new object[] {pyObj, null}; + bool success = (bool)convert.Invoke(converterAttribute, @params); + if (!success) + { + pyObj.Dispose(); } + result = @params[1]; + return success; } return TryConvert; } - internal delegate bool TryConvertFromPythonDelegate(IntPtr pyObj, out object result); + internal delegate bool TryConvertFromPythonDelegate(BorrowedReference pyObj, out object result); static readonly ConcurrentDictionary TypeConverterCache = new ConcurrentDictionary(); diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index 667fc6f00..07616ae39 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -110,16 +110,16 @@ static IPyObjectEncoder[] GetEncoders(Type type) #region Decoding static readonly ConcurrentDictionary pythonToClr = new ConcurrentDictionary(); - internal static bool TryDecode(IntPtr pyHandle, IntPtr pyType, Type targetType, out object result) + internal static bool TryDecode(BorrowedReference obj, BorrowedReference objType, Type targetType, out object result) { - if (pyHandle == IntPtr.Zero) throw new ArgumentNullException(nameof(pyHandle)); - if (pyType == IntPtr.Zero) throw new ArgumentNullException(nameof(pyType)); + if (obj.IsNull) throw new ArgumentNullException(nameof(obj)); + if (objType.IsNull) throw new ArgumentNullException(nameof(objType)); if (targetType == null) throw new ArgumentNullException(nameof(targetType)); - var decoder = pythonToClr.GetOrAdd(new TypePair(pyType, targetType), pair => GetDecoder(pair.PyType, pair.ClrType)); + var decoder = pythonToClr.GetOrAdd(new TypePair(objType.DangerousGetAddress(), targetType), pair => GetDecoder(pair.PyType, pair.ClrType)); result = null; if (decoder == null) return false; - return decoder.Invoke(pyHandle, out result); + return decoder.Invoke(obj, out result); } static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type targetType) @@ -136,9 +136,9 @@ static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type var decode = genericDecode.MakeGenericMethod(targetType); - bool TryDecode(IntPtr pyHandle, out object result) + bool TryDecode(BorrowedReference pyHandle, out object result) { - var pyObj = new PyObject(Runtime.SelfIncRef(pyHandle)); + var pyObj = new PyObject(pyHandle); var @params = new object[] { pyObj, null }; bool success = (bool)decode.Invoke(decoder, @params); if (!success) diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 9a6ebb6cf..265e7da28 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -82,8 +82,7 @@ static IntPtr FromItems(PyObject[] items) if (items[i] == null) throw new ArgumentNullException(); IntPtr ptr = items[i].obj; - Runtime.PyTuple_SetItem(obj, i, ptr); - Runtime.CheckExceptionOccurred(); + PythonException.ThrowIfIsNotZero(Runtime.PyTuple_SetItem(obj, i, ptr)); Runtime.XIncref(ptr); } } catch { From 4c96ddcfb4aaf77fbdf1d18dff6e5332cc0648a7 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 10 Mar 2020 23:30:47 -0700 Subject: [PATCH 115/240] allow borrowing from NewReference implemented as an implicit conversion --- src/embed_tests/References.cs | 15 +++++++++++++++ src/runtime/NewReference.cs | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/src/embed_tests/References.cs b/src/embed_tests/References.cs index 4c7124907..1d29e85c7 100644 --- a/src/embed_tests/References.cs +++ b/src/embed_tests/References.cs @@ -36,5 +36,20 @@ public void MoveToPyObject_SetsNull() reference.Dispose(); } } + + [Test] + public void CanBorrowFromNewReference() + { + var dict = new PyDict(); + NewReference reference = Runtime.PyDict_Items(dict.Handle); + try + { + PythonException.ThrowIfIsNotZero(Runtime.PyList_Reverse(reference)); + } + finally + { + reference.Dispose(); + } + } } } diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs index 3ab4b6530..6e66232d0 100644 --- a/src/runtime/NewReference.cs +++ b/src/runtime/NewReference.cs @@ -11,6 +11,10 @@ ref struct NewReference { IntPtr pointer; + [Pure] + public static implicit operator BorrowedReference(in NewReference reference) + => new BorrowedReference(reference.pointer); + /// /// Returns wrapper around this reference, which now owns /// the pointer. Sets the original reference to null, as it no longer owns it. @@ -36,6 +40,7 @@ public void Dispose() /// /// Creates from a raw pointer /// + [Pure] public static NewReference DangerousFromPointer(IntPtr pointer) => new NewReference {pointer = pointer}; From 6323dde92be5c87aa1bb8ae208b7f0644fdffdae Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:13:09 -0700 Subject: [PATCH 116/240] workaround for https://github.com/ufcpp/NonCopyableAnalyzer/issues/14 --- src/runtime/NewReference.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs index 6e66232d0..0c93e9e18 100644 --- a/src/runtime/NewReference.cs +++ b/src/runtime/NewReference.cs @@ -15,6 +15,10 @@ ref struct NewReference public static implicit operator BorrowedReference(in NewReference reference) => new BorrowedReference(reference.pointer); + [Pure] + [Obsolete("This should be replaced by implicit conversion after https://github.com/ufcpp/NonCopyableAnalyzer/issues/14")] + public BorrowedReference Borrow() => new BorrowedReference(this.pointer); + /// /// Returns wrapper around this reference, which now owns /// the pointer. Sets the original reference to null, as it no longer owns it. From ad75c72218f854d93065d06cf8300d146ec4ff92 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:15:58 -0700 Subject: [PATCH 117/240] ManagedType.GetManagedObject(BorrowedReference) --- src/runtime/managedtype.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index c59ead405..27c694b95 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -18,6 +18,7 @@ internal abstract class ManagedType /// /// Given a Python object, return the associated managed object or null. /// + [Obsolete("Use GetManagedObject(BorrowedReference)")] internal static ManagedType GetManagedObject(IntPtr ob) { if (ob != IntPtr.Zero) @@ -45,6 +46,9 @@ internal static ManagedType GetManagedObject(IntPtr ob) return null; } + internal static ManagedType GetManagedObject(BorrowedReference ob) + => ob.IsNull ? null : GetManagedObject(ob.DangerousGetAddress()); + internal static ManagedType GetManagedObjectErr(IntPtr ob) { From 9e9677972a733f571b2fdce20a1599e6f0af9fc7 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:17:14 -0700 Subject: [PATCH 118/240] fixed potential crash in MethodBinding.__signature__ --- src/runtime/methodbinding.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index 9f9e006d1..d8138d36e 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -76,7 +76,7 @@ PyObject Singature { var parameters = new PyList(); var parameterClass = primaryParameters.Length > 0 ? Runtime.InspectModule.GetAttr("Parameter") : null; - var positionalOrKeyword = primaryParameters.Length > 0 ? parameterClass.GetAttr("POSITIONAL_OR_KEYWORD") : null; + var positionalOrKeyword = parameterClass?.GetAttr("POSITIONAL_OR_KEYWORD"); for (int i = 0; i < primaryParameters.Length; i++) { var parameter = primaryParameters[i]; var alternatives = infos.Select(info => { @@ -141,7 +141,11 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) return om.pyHandle; case "__signature__": var sig = self.Singature; - return sig.Handle; + if (sig is null) + { + return Runtime.PyObject_GenericGetAttr(ob, key); + } + return sig.Reference.DangerousIncRefOrNull(); case "__name__": var pyName = self.m.GetName(); return pyName == IntPtr.Zero From 34eed71f2b3b5dcc329535ec57ee28a88fb5edb2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:25:07 -0700 Subject: [PATCH 119/240] fixed PythonException construction with *Reference types --- src/runtime/BorrowedReference.cs | 5 ++ src/runtime/pyobject.cs | 2 +- src/runtime/pythonexception.cs | 95 ++++++++++++++++++-------------- src/runtime/runtime.cs | 5 +- 4 files changed, 63 insertions(+), 44 deletions(-) diff --git a/src/runtime/BorrowedReference.cs b/src/runtime/BorrowedReference.cs index a3bf29056..528516b0b 100644 --- a/src/runtime/BorrowedReference.cs +++ b/src/runtime/BorrowedReference.cs @@ -22,4 +22,9 @@ public BorrowedReference(IntPtr pointer) this.pointer = pointer; } } + + static class BorrowedReferenceExtensions { + public static IntPtr DangerousIncRefOrNull(this in BorrowedReference reference) + => reference.IsNull ? IntPtr.Zero : Runtime.SelfIncRef(reference.DangerousGetAddress()); + } } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 184057450..79a7188cb 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -201,7 +201,7 @@ public IntPtr[] GetTrackedHandles() return new IntPtr[] { obj }; } - internal IntPtr GetPythonTypeHandle() => Runtime.PyObject_Type(obj); + internal BorrowedReference GetPythonTypeHandle() => new BorrowedReference(Runtime.PyObject_TYPE(obj)); /// /// GetPythonType Method diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 1ce4a7387..269dce262 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -24,66 +24,75 @@ public class PythonException : System.Exception, IPyDisposable public PythonException() { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.PyErr_Fetch(out _pyType, out _pyValue, out _pyTB); + Runtime.PyErr_Fetch(out var type, out var value, out var traceback); + _pyType = type.DangerousGetAddress(); + _pyValue = value.DangerousGetAddress(); + _pyTB = traceback.DangerousGetAddress(); if (_pyType != IntPtr.Zero && _pyValue != IntPtr.Zero) { - string type; string message; Runtime.XIncref(_pyType); using (var pyType = new PyObject(_pyType)) using (PyObject pyTypeName = pyType.GetAttr("__name__")) { - type = pyTypeName.ToString(); + _pythonTypeName = pyTypeName.ToString(); } - _pythonTypeName = type; - Runtime.XIncref(_pyValue); using (var pyValue = new PyObject(_pyValue)) { message = pyValue.ToString(); } - _message = type + " : " + message; + _message = _pythonTypeName + " : " + message; } if (_pyTB != IntPtr.Zero) { - this._traceback = TracebackHandleToString(_pyTB); + this._traceback = TracebackHandleToString(new BorrowedReference(_pyTB)); } PythonEngine.ReleaseLock(gs); } - private PythonException(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle, + private PythonException(BorrowedReference pyTypeHandle, + BorrowedReference pyValueHandle, + BorrowedReference pyTracebackHandle, string message, string pythonTypeName, string traceback, Exception innerException) : base(message, innerException) { - _pyType = pyTypeHandle; - _pyValue = pyValueHandle; - _pyTB = pyTracebackHandle; + _pyType = pyTypeHandle.DangerousIncRefOrNull(); + _pyValue = pyValueHandle.DangerousIncRefOrNull(); + _pyTB = pyTracebackHandle.DangerousIncRefOrNull(); _message = message; _pythonTypeName = pythonTypeName ?? _pythonTypeName; _traceback = traceback ?? _traceback; } - internal static Exception FromPyErr() { - IntPtr gs = PythonEngine.AcquireLock(); + internal static Exception FromPyErr() + { Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); - var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); - PythonEngine.ReleaseLock(gs); - return result; + using (pyTypeHandle) + using (pyValueHandle) + using (pyTracebackHandle) { + return FromPyErr( + pyTypeHandle: pyTypeHandle.Borrow(), + pyValueHandle: pyValueHandle.Borrow(), + pyTracebackHandle: pyTracebackHandle.Borrow()); + } } internal static Exception FromPyErrOrNull() { - IntPtr gs = PythonEngine.AcquireLock(); Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); - if (pyValueHandle == IntPtr.Zero && pyTypeHandle == IntPtr.Zero && pyTracebackHandle == IntPtr.Zero) - { - return null; + using (pyTypeHandle) + using (pyValueHandle) + using (pyTracebackHandle) { + if (pyValueHandle.IsNull() && pyTypeHandle.IsNull() && pyTracebackHandle.IsNull()) { + return null; + } + + var result = FromPyErr(pyTypeHandle.Borrow(), pyValueHandle.Borrow(), pyTracebackHandle.Borrow()); + return result; } - var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); - PythonEngine.ReleaseLock(gs); - return result; } /// @@ -95,15 +104,20 @@ internal static Exception ThrowLastAsClrException() { IntPtr gs = PythonEngine.AcquireLock(); try { Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); - var clrObject = ManagedType.GetManagedObject(pyValueHandle) as CLRObject; - if (clrObject?.inst is Exception e) { + using (pyTypeHandle) + using (pyValueHandle) + using (pyTracebackHandle) { + var clrObject = ManagedType.GetManagedObject(pyValueHandle.Borrow()) as CLRObject; + if (clrObject?.inst is Exception e) { #if NETSTANDARD - ExceptionDispatchInfo.Capture(e).Throw(); + ExceptionDispatchInfo.Capture(e).Throw(); #endif - throw e; + throw e; + } + + var result = FromPyErr(pyTypeHandle.Borrow(), pyValueHandle.Borrow(), pyTracebackHandle.Borrow()); + throw result; } - var result = FromPyErr(pyTypeHandle, pyValueHandle, pyTracebackHandle); - throw result; } finally { PythonEngine.ReleaseLock(gs); } @@ -112,7 +126,7 @@ internal static Exception ThrowLastAsClrException() { /// /// Requires lock to be acquired elsewhere /// - static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyTracebackHandle) { + static Exception FromPyErr(BorrowedReference pyTypeHandle, BorrowedReference pyValueHandle, BorrowedReference pyTracebackHandle) { Exception inner = null; string pythonTypeName = null, msg = "", traceback = null; @@ -121,7 +135,7 @@ static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyT return e; } - if (pyTypeHandle != IntPtr.Zero && pyValueHandle != IntPtr.Zero) + if (!pyTypeHandle.IsNull && !pyValueHandle.IsNull) { if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), out object decoded) && decoded is Exception decodedException) { @@ -130,7 +144,6 @@ static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyT string type; string message; - Runtime.XIncref(pyTypeHandle); using (var pyType = new PyObject(pyTypeHandle)) using (PyObject pyTypeName = pyType.GetAttr("__name__")) { @@ -139,21 +152,21 @@ static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyT pythonTypeName = type; - Runtime.XIncref(pyValueHandle); using (var pyValue = new PyObject(pyValueHandle)) { message = pyValue.ToString(); var cause = pyValue.GetAttr("__cause__", null); if (cause != null && cause.Handle != Runtime.PyNone) { - IntPtr innerTraceback = cause.GetAttr("__traceback__", null)?.Handle ?? IntPtr.Zero; - Runtime.XIncref(innerTraceback); - inner = FromPyErr(cause.GetPythonTypeHandle(), cause.obj, innerTraceback); - Runtime.XDecref(innerTraceback); + using var innerTraceback = cause.GetAttr("__traceback__", null); + inner = FromPyErr( + pyTypeHandle: cause.GetPythonTypeHandle(), + pyValueHandle: cause.Reference, + pyTracebackHandle: innerTraceback is null ? new BorrowedReference() : innerTraceback.Reference); } } msg = type + " : " + message; } - if (pyTracebackHandle != IntPtr.Zero) + if (!pyTracebackHandle.IsNull) { traceback = TracebackHandleToString(pyTracebackHandle); } @@ -162,13 +175,13 @@ static Exception FromPyErr(IntPtr pyTypeHandle, IntPtr pyValueHandle, IntPtr pyT msg, pythonTypeName, traceback, inner); } - static string TracebackHandleToString(IntPtr tracebackHandle) { - if (tracebackHandle == IntPtr.Zero) { + static string TracebackHandleToString(BorrowedReference tracebackHandle) { + if (tracebackHandle.IsNull) { throw new ArgumentNullException(nameof(tracebackHandle)); } PyObject tracebackModule = PythonEngine.ImportModule("traceback"); - using var traceback = new PyObject(Runtime.SelfIncRef(tracebackHandle)); + using var traceback = new PyObject(tracebackHandle); PyList stackLines = new PyList(tracebackModule.InvokeMethod("format_tb", traceback)); stackLines.Reverse(); var result = new StringBuilder(); diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 893160a71..ca5507d8c 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1753,7 +1753,8 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) internal static IntPtr PyErr_Occurred() => Delegates.PyErr_Occurred(); - internal static void PyErr_Fetch(out IntPtr ob, out IntPtr val, out IntPtr tb) => Delegates.PyErr_Fetch(out ob, out val, out tb); + internal static void PyErr_Fetch(out NewReference type, out NewReference value, out NewReference traceback) + => Delegates.PyErr_Fetch(out type, out value, out traceback); internal static void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_Restore(ob, val, tb); @@ -3163,7 +3164,7 @@ int updatepath internal static PyErr_FetchDelegate PyErr_Fetch { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate void PyErr_FetchDelegate(out IntPtr ob, out IntPtr val, out IntPtr tb); + internal delegate void PyErr_FetchDelegate(out NewReference ob, out NewReference val, out NewReference tb); internal static PyErr_RestoreDelegate PyErr_Restore { get; } From 1e5f49f9b6b6f90beb00801ae15de2462b414cd3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:29:33 -0700 Subject: [PATCH 120/240] improved refcounting for base type overrides --- src/runtime/typemanager.cs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 9c08385c2..c21b7b470 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -144,19 +144,18 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) int extraTypeDataOffset = ob_size - MetaType.ExtraTypeDataSize; try { - IntPtr base_ = GetBaseType(clrType, out IntPtr bases); - if (base_ != IntPtr.Zero) + using PyTuple baseTuple = GetBaseTypeTuple(clrType); + if (baseTuple.Length() > 0) { - Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); - Runtime.XIncref(base_); + IntPtr primaryBase = baseTuple[0].Reference.DangerousIncRefOrNull(); + Marshal.WriteIntPtr(type, TypeOffset.tp_base, primaryBase); - if (bases != IntPtr.Zero) { - Marshal.WriteIntPtr(type, TypeOffset.tp_bases, bases); - Runtime.XIncref(bases); + if (baseTuple.Length() > 1) { + Marshal.WriteIntPtr(type, TypeOffset.tp_bases, baseTuple.Reference.DangerousIncRefOrNull()); } - int baseSize = checked((int)Marshal.ReadIntPtr(base_, TypeOffset.tp_basicsize)); - if (!ClassObject.IsManagedType(base_)) + int baseSize = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.tp_basicsize)); + if (!ClassObject.IsManagedType(primaryBase)) { // custom base type is a Python type, so we must allocate additional space for GC handle extraTypeDataOffset = baseSize; @@ -164,7 +163,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) ob_size = baseSize + MetaType.ExtraTypeDataSize; } else { - extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(base_, TypeOffset.clr_gchandle_offset)); + extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.clr_gchandle_offset)); ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); ob_size = baseSize; } @@ -273,26 +272,26 @@ static string CleanupFullName(string fullTypeName) return name; } - static IntPtr GetBaseType(Type clrType, out IntPtr baseTypes) + static PyTuple GetBaseTypeTuple(Type clrType) { - baseTypes = IntPtr.Zero; - if (clrType == typeof(Exception)) - { - return Exceptions.Exception; + if (clrType == typeof(Exception)) { + var exception = new PyObject(new BorrowedReference(Exceptions.Exception)); + return PyTuple.FromSingleElement(exception); } var baseOverride = Util.GetLatestAttribute(clrType) ?? BaseTypeAttributeBase.Default; var types = baseOverride.BaseTypes(clrType); - if (types.Length() == 0) return IntPtr.Zero; + if (types is null) throw new InvalidOperationException(); + if (types.Length() == 0) return new PyTuple(); for (int index = 0; index < types.Length(); index++) { IntPtr baseType = Runtime.PyTuple_GetItem(types.Handle, index); if (!PyType.IsTypeType(baseType)) { throw new InvalidOperationException("Entries in base types must be Python types themselves"); } } - baseTypes = types.Handle; - return types[0].Handle; + + return types; } internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) From a65e97766504f5e02263570887d8ea4d42b433a4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 17 Mar 2020 21:44:56 -0700 Subject: [PATCH 121/240] dispose temporary object in CallableObject test class setup --- src/embed_tests/CallableObject.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index 2915f9dad..4e6ed1723 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -10,7 +10,7 @@ class CallableObject { public void SetUp() { PythonEngine.Initialize(); using (Py.GIL()) { - var locals = new PyDict(); + using var locals = new PyDict(); PythonEngine.Exec(CallViaInheritance.BaseClassSource, locals: locals.Handle); CustomBaseTypeAttribute.BaseClass = locals[CallViaInheritance.BaseClassName]; } @@ -20,7 +20,6 @@ public void SetUp() { public void Dispose() { PythonEngine.Shutdown(); } - [Test] public void CallMethodMakesObjectCallable() { var doubler = new DerivedDoubler(); @@ -29,7 +28,6 @@ public void CallMethodMakesObjectCallable() { Assert.AreEqual(doubler.__call__(21), (int)applyObjectTo21(doubler.ToPython())); } } - [Test] public void CallMethodCanBeInheritedFromPython() { var callViaInheritance = new CallViaInheritance(); From 53e462438ef1aec33f148780abc11c157f566c51 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:27:09 -0700 Subject: [PATCH 122/240] re-enabled ReInitialize test --- src/embed_tests/pyinitialize.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/embed_tests/pyinitialize.cs b/src/embed_tests/pyinitialize.cs index ea1d8d023..e2aaf89db 100644 --- a/src/embed_tests/pyinitialize.cs +++ b/src/embed_tests/pyinitialize.cs @@ -43,13 +43,9 @@ public static void LoadSpecificArgs() } /// - /// Failing test demonstrating current issue with OverflowException (#376) - /// and ArgumentException issue after that one is fixed. - /// More complex version of StartAndStopTwice test + /// Regression test for https://github.com/pythonnet/pythonnet/pull/376 /// [Test] - [Ignore("GH#376: System.OverflowException : Arithmetic operation resulted in an overflow")] - //[Ignore("System.ArgumentException : Cannot pass a GCHandle across AppDomains")] public void ReInitialize() { var code = "from System import Int32\n"; From 77693a0a05366957e9ae562141632a249eddeb36 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:27:27 -0700 Subject: [PATCH 123/240] minor change to CallableObject tests class --- src/embed_tests/CallableObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index 4e6ed1723..bbdf1b21b 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -60,6 +60,7 @@ class CustomBaseTypeAttribute : BaseTypeAttributeBase { internal static PyObject BaseClass; public override PyTuple BaseTypes(Type type) { + Assert.Greater(BaseClass.Refcount, 0); return type != typeof(CallViaInheritance) ? base.BaseTypes(type) : PyTuple.FromSingleElement(BaseClass); From 1b381a7a895c7c6d789da0324611de2e150a5264 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:28:00 -0700 Subject: [PATCH 124/240] BorrowedReference equality comparison operators --- src/runtime/BorrowedReference.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/runtime/BorrowedReference.cs b/src/runtime/BorrowedReference.cs index 528516b0b..5cff10512 100644 --- a/src/runtime/BorrowedReference.cs +++ b/src/runtime/BorrowedReference.cs @@ -21,6 +21,17 @@ public BorrowedReference(IntPtr pointer) { this.pointer = pointer; } + + public bool Equals(BorrowedReference other) => this.pointer == other.pointer; + + public static bool operator==(BorrowedReference reference, BorrowedReference other) + => reference.pointer == other.pointer; + public static bool operator!=(BorrowedReference reference, BorrowedReference other) + => reference.pointer != other.pointer; + public static bool operator==(BorrowedReference reference, IntPtr rawPointer) + => reference.pointer == rawPointer; + public static bool operator!=(BorrowedReference reference, IntPtr rawPointer) + => reference.pointer != rawPointer; } static class BorrowedReferenceExtensions { From e8a1cf9d77340fd9908815873f9740288d1012e1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:36:09 -0700 Subject: [PATCH 125/240] added a few overloads, that use BorrowedReference --- src/runtime/classderived.cs | 2 +- src/runtime/interfaceobject.cs | 2 +- src/runtime/managedtype.cs | 2 ++ src/runtime/pyscope.cs | 1 + src/runtime/runtime.cs | 6 ++++++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index e56e25a62..df6b9d89a 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -248,7 +248,7 @@ internal static Type CreateDerivedType(string name, MethodAttributes.HideBySig, CallingConventions.Standard, typeof(void), - Type.EmptyTypes); + System.Type.EmptyTypes); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("Finalize")); diff --git a/src/runtime/interfaceobject.cs b/src/runtime/interfaceobject.cs index 616ced6bd..acae39650 100644 --- a/src/runtime/interfaceobject.cs +++ b/src/runtime/interfaceobject.cs @@ -19,7 +19,7 @@ internal InterfaceObject(Type tp) : base(tp) var coclass = (CoClassAttribute)Attribute.GetCustomAttribute(tp, cc_attr); if (coclass != null) { - ctor = coclass.CoClass.GetConstructor(Type.EmptyTypes); + ctor = coclass.CoClass.GetConstructor(System.Type.EmptyTypes); } } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 27c694b95..41951a612 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -13,6 +13,8 @@ internal abstract class ManagedType internal GCHandle gcHandle; // Native handle internal IntPtr pyHandle; // PyObject * internal IntPtr tpHandle; // PyType * + internal BorrowedReference Type => new BorrowedReference(this.tpHandle); + internal BorrowedReference Instance => new BorrowedReference(this.tpHandle); /// diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index b22f7d213..75918e47b 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -35,6 +35,7 @@ public class PyScope : DynamicObject, IPyDisposable /// the variable dict of the scope. /// internal readonly IntPtr variables; + internal BorrowedReference VarsReference => new BorrowedReference(variables); private bool _isDisposed; private bool _finalized = false; diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index ca5507d8c..a3580964c 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -884,6 +884,12 @@ internal static unsafe IntPtr PyObject_TYPE(IntPtr op) : new IntPtr((void*)(*((ulong*)p + n))); } + internal static BorrowedReference PyObject_TYPE(BorrowedReference reference) { + return reference.IsNull + ? throw new ArgumentNullException(nameof(reference)) + : new BorrowedReference(PyObject_TYPE(reference.DangerousGetAddress())); + } + /// /// Managed version of the standard Python C API PyObject_Type call. /// This version avoids a managed <-> unmanaged transition. From 12659d3c6ac49a59b4eed5f08892ea67835c7567 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:37:17 -0700 Subject: [PATCH 126/240] fixed refcounting in PyTuple.FromItems in case of exception --- src/runtime/pytuple.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 265e7da28..716fc4249 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -82,8 +82,8 @@ static IntPtr FromItems(PyObject[] items) if (items[i] == null) throw new ArgumentNullException(); IntPtr ptr = items[i].obj; - PythonException.ThrowIfIsNotZero(Runtime.PyTuple_SetItem(obj, i, ptr)); Runtime.XIncref(ptr); + PythonException.ThrowIfIsNotZero(Runtime.PyTuple_SetItem(obj, i, ptr)); } } catch { Runtime.XDecref(obj); From 751c5db36361421d0b82e696441593658032c08d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:38:16 -0700 Subject: [PATCH 127/240] minor refactoring --- src/runtime/classobject.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 8e308a459..630d38491 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -309,11 +309,12 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) return callBinder.Invoke(ob, args, kw); } - using var super = new PyObject(Runtime.SelfIncRef(Runtime.PySuper_Type)); - using var self = new PyObject(Runtime.SelfIncRef(ob)); - using var none = new PyObject(Runtime.SelfIncRef(Runtime.PyNone)); - foreach (IntPtr managedTypeDerivingFromPython in GetTypesWithPythonBasesInHierarchy(tp)) { - using var @base = super.Invoke(new PyObject(managedTypeDerivingFromPython), self); + using var super = new PyObject(new BorrowedReference(Runtime.PySuper_Type)); + using var self = new PyObject(new BorrowedReference(ob)); + using var none = new PyObject(new BorrowedReference(Runtime.PyNone)); + foreach (IntPtr rawTypePointer in GetTypesWithPythonBasesInHierarchy(tp)) { + using var managedTypeDerivingFromPython = new PyObject(new BorrowedReference(rawTypePointer)); + using var @base = super.Invoke(managedTypeDerivingFromPython, self); using var call = @base.GetAttrOrElse("__call__", none); if (call.Handle == Runtime.PyNone) continue; From 8a3dfd5e07b06927a953b6bdf0432ad5f6663453 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:38:40 -0700 Subject: [PATCH 128/240] IsManagedType overload for BorrowedReference --- src/runtime/classobject.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 630d38491..51c9ce9b2 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -403,5 +403,8 @@ internal static bool IsManagedType(IntPtr tp) var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); return (flags & TypeFlags.Managed) != 0; } + /// Checks if specified type is a CLR type + internal static bool IsManagedType(BorrowedReference type) + => IsManagedType(type.DangerousGetAddress()); } } From b927ecbcb7795b42f28c410cf3a2f6a4f18701d3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:42:48 -0700 Subject: [PATCH 129/240] fixed ManagedType.Instance --- src/runtime/managedtype.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 41951a612..d01702134 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -14,7 +14,7 @@ internal abstract class ManagedType internal IntPtr pyHandle; // PyObject * internal IntPtr tpHandle; // PyType * internal BorrowedReference Type => new BorrowedReference(this.tpHandle); - internal BorrowedReference Instance => new BorrowedReference(this.tpHandle); + internal BorrowedReference Instance => new BorrowedReference(this.pyHandle); /// From 110c66121f8ab611fb8c2540e3768646431326d1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:48:38 -0700 Subject: [PATCH 130/240] added DebugUtil.AssertRefcount --- src/runtime/clrobject.cs | 4 +++- src/runtime/debughelper.cs | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 8634a924d..414e911ca 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -78,7 +78,9 @@ internal static NewReference MakeNewReference(object obj) if (obj is null) throw new ArgumentNullException(nameof(obj)); // TODO: CLRObject currently does not have Dispose or finalizer which might change in the future - return NewReference.DangerousFromPointer(GetInstHandle(obj)); + IntPtr handle = GetInstHandle(obj); + DebugUtil.AssertRefcount(handle); + return NewReference.DangerousFromPointer(handle); } } } diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index 26f62ef05..5e3fad8f0 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -145,5 +145,12 @@ public static void EnsureGIL() Debug.Assert(Runtime.PyGILState_Check() == 1, "GIL must be acquired"); } } + + [Conditional("DEBUG")] + public static void AssertRefcount(IntPtr ob, long expected = 1) { + long refcount = Runtime.Refcount(ob); + if (refcount != expected) + throw new InvalidProgramException(); + } } } From 598995a9b46fcc33c91fe54bf16d2903afe78bce Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 13:51:29 -0700 Subject: [PATCH 131/240] added debug checks to XIncref and XDecref --- src/runtime/runtime.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index a3580964c..b8a794b0f 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -599,6 +599,18 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) /// internal static unsafe void XIncref(IntPtr op) { + DebugUtil.EnsureGIL(); +#if DEBUG + if (op == IntPtr.Zero) + throw new ArgumentNullException(nameof(op)); + long refcount = Refcount(op); + if (refcount < 0 || refcount > 100000) + throw new ArgumentOutOfRangeException( + message: "Reference count is insane", + paramName: nameof(op), + actualValue: refcount); +#endif + #if PYTHON_WITH_PYDEBUG || NETSTANDARD Py_IncRef(op); return; @@ -629,6 +641,18 @@ internal static IntPtr SelfIncRef(IntPtr op) internal static unsafe void XDecref(IntPtr op) { + DebugUtil.EnsureGIL(); +#if DEBUG + if (op == IntPtr.Zero) + throw new ArgumentNullException(nameof(op)); + long refcount = Refcount(op); + if (refcount <= 0 || refcount > 100000) + throw new ArgumentOutOfRangeException( + paramName: nameof(refcount), + actualValue: refcount, + message: "Reference count is insane"); +#endif + #if PYTHON_WITH_PYDEBUG || NETSTANDARD Py_DecRef(op); return; From d4eef7ec63db2ff52ef2e0682aa9a2601de23ed0 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 14:48:51 -0700 Subject: [PATCH 132/240] use *Reference types in PyObject_GetItem --- src/runtime/pyobject.cs | 7 ++++--- src/runtime/pyscope.cs | 9 ++++----- src/runtime/runtime.cs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 79a7188cb..aae949415 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -473,12 +473,13 @@ public virtual PyObject GetItem(PyObject key) DebugUtil.EnsureGIL(); - IntPtr op = Runtime.PyObject_GetItem(obj, key.obj); - if (op == IntPtr.Zero) + using var op = Runtime.PyObject_GetItem(Reference, key.Reference); + if (op.IsNull()) { throw PythonException.ThrowLastAsClrException(); } - return new PyObject(op); + + return op.MoveToPyObject(); } diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index 75918e47b..9a97b9695 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -436,18 +436,17 @@ public bool TryGet(string name, out PyObject value) { if (Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0) { - IntPtr op = Runtime.PyObject_GetItem(variables, pyKey.obj); - if (op == IntPtr.Zero) + using var op = Runtime.PyObject_GetItem(VarsReference, pyKey.Reference); + if (op.IsNull()) { throw PythonException.ThrowLastAsClrException(); } - if (op == Runtime.PyNone) + if (op.IsNone()) { - Runtime.XDecref(op); value = null; return true; } - value = new PyObject(op); + value = op.MoveToPyObject(); return true; } else diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index b8a794b0f..024b8ac61 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -962,7 +962,7 @@ internal static bool PyObject_IsIterable(IntPtr pointer) internal static int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value) => Delegates.PyObject_SetAttr(pointer, name, value); - internal static IntPtr PyObject_GetItem(IntPtr pointer, IntPtr key) => Delegates.PyObject_GetItem(pointer, key); + internal static NewReference PyObject_GetItem(BorrowedReference pointer, BorrowedReference key) => Delegates.PyObject_GetItem(pointer, key); internal static int PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value) => Delegates.PyObject_SetItem(pointer, key, value); @@ -2373,7 +2373,7 @@ internal delegate int Py_MainDelegate( internal static PyObject_GetItemDelegate PyObject_GetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate IntPtr PyObject_GetItemDelegate(IntPtr pointer, IntPtr key); + internal delegate NewReference PyObject_GetItemDelegate(BorrowedReference pointer, BorrowedReference key); internal static PyObject_SetItemDelegate PyObject_SetItem { get; } From 047b7e13b8a60a5a933d5bc2de3d1f1b4dda6c07 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 14:49:15 -0700 Subject: [PATCH 133/240] check for Python exceptions in PyObject.ToString --- src/runtime/pyobject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index aae949415..dacb22054 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -1064,6 +1064,7 @@ public override string ToString() { DebugUtil.EnsureGIL(); IntPtr strval = Runtime.PyObject_Unicode(obj); + PythonException.ThrowIfIsNull(strval); string result = Runtime.GetManagedString(strval); Runtime.XDecref(strval); return result; From f5b2b9deff172bed7902632c1194002fb054b381 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 14:54:07 -0700 Subject: [PATCH 134/240] MethodBinding: don't incref null target --- src/runtime/methodbinding.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index d8138d36e..a2303d293 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -19,7 +19,7 @@ internal class MethodBinding : ExtensionType public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) { - Runtime.XIncref(target); + if (target != IntPtr.Zero) Runtime.XIncref(target); this.target = target; Runtime.XIncref(targetType); From d81e04f404807de6ed4367fede709f026eeea84d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 18 Mar 2020 16:35:45 -0700 Subject: [PATCH 135/240] fixed deallocation of objects after runtime restart ObjectOffset.magic method, that was used to determine the offset to GCHandle was comparing object metatype to Runtime.CLRMetaType, which has changed due to runtime restart. Overall, ObjectOffset.magic had too much responsibility and relatively unclear behavior. It was replaced with one of: - GetDefaultGCHandleOffset, which returns GCHandle offset for types deriving from regular Python types - ReflectedObjectGCHandle, that returns GCHandle offset for reflected CLR object instances - InstanceGCHandle, that does the same based on reflected object type rather than instance The way tp_basicsize and clr_gchandle_offset are calculated is made more robust. It now requires an explicit base type to be specified, and counts derived type size and GCHandle offset from it. --- src/runtime/BaseTypeAttributeBase.cs | 2 +- src/runtime/classbase.cs | 3 +- src/runtime/classderived.cs | 4 +-- src/runtime/classobject.cs | 12 ------- src/runtime/clrobject.cs | 5 +-- src/runtime/extensiontype.cs | 6 ++-- src/runtime/interop.cs | 52 +++++++++++++++++---------- src/runtime/managedtype.cs | 52 +++++++++++++++++---------- src/runtime/methodbinding.cs | 24 +++++++------ src/runtime/methodobject.cs | 2 +- src/runtime/modulefunctionobject.cs | 4 +-- src/runtime/moduleobject.cs | 4 +-- src/runtime/propertyobject.cs | 9 ++--- src/runtime/typemanager.cs | 54 +++++++++++++++------------- 14 files changed, 131 insertions(+), 102 deletions(-) diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs index 549623dc0..c904cc5bb 100644 --- a/src/runtime/BaseTypeAttributeBase.cs +++ b/src/runtime/BaseTypeAttributeBase.cs @@ -27,7 +27,7 @@ public virtual PyTuple BaseTypes(Type type) { return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(bc.pyHandle))); } - return new PyTuple(); + return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(Runtime.PyBaseObjectType))); } internal static BaseTypeAttributeBase Default { get; } = new BaseTypeAttributeBase(); diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs index 41636c404..65420726f 100644 --- a/src/runtime/classbase.cs +++ b/src/runtime/classbase.cs @@ -290,7 +290,8 @@ public static IntPtr tp_repr(IntPtr ob) /// public static void tp_dealloc(IntPtr ob) { - ManagedType self = GetManagedObject(ob); + var reference = new BorrowedReference(ob); + var self = GetManagedObject(reference, ObjectOffset.ReflectedObjectGCHandle(reference)); IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.DictOffset(ob)); if (dict != IntPtr.Zero) { diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index df6b9d89a..aadbb6969 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -74,7 +74,7 @@ internal ClassDerivedObject(Type tp) : base(tp) // So we don't call PyObject_GC_Del here and instead we set the python // reference to a weak reference so that the C# object can be collected. GCHandle gc = GCHandle.Alloc(self, GCHandleType.Weak); - Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)gc); + Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.InstanceGCHandle(self.Type), (IntPtr)gc); self.gcHandle.Free(); self.gcHandle = gc; } @@ -100,7 +100,7 @@ internal static IntPtr ToPython(IPythonDerivedType obj) if (Runtime.Refcount(self.pyHandle) == 1) { GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal); - Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)gc); + Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.InstanceGCHandle(self.Type), (IntPtr)gc); self.gcHandle.Free(); self.gcHandle = gc; diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 51c9ce9b2..0003066d9 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -394,17 +394,5 @@ internal static IEnumerable GetTypesWithPythonBasesInHierarchy(IntPtr tp } } } - - /// - /// Checks if specified type is a CLR type - /// - internal static bool IsManagedType(IntPtr tp) - { - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - return (flags & TypeFlags.Managed) != 0; - } - /// Checks if specified type is a CLR type - internal static bool IsManagedType(BorrowedReference type) - => IsManagedType(type.DangerousGetAddress()); } } diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 414e911ca..31b852f4a 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -22,10 +22,11 @@ internal CLRObject(object ob, IntPtr tp) } } - GCHandle gc = GCHandle.Alloc(this); - Marshal.WriteIntPtr(py, ObjectOffset.magic(py), (IntPtr)gc); tpHandle = tp; pyHandle = py; + GCHandle gc = GCHandle.Alloc(this); + int gcHandleOffset = ObjectOffset.ReflectedObjectGCHandle(this.Instance); + Marshal.WriteIntPtr(py, gcHandleOffset, (IntPtr)gc); gcHandle = gc; inst = ob; diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index 6585180c1..713babbd6 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -29,7 +29,7 @@ public ExtensionType() IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); GCHandle gc = GCHandle.Alloc(this); - Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc); + Marshal.WriteIntPtr(py, ObjectOffset.GetDefaultGCHandleOffset(), (IntPtr)gc); // We have to support gc because the type machinery makes it very // hard not to - but we really don't have a need for it in most @@ -48,7 +48,7 @@ public ExtensionType() /// /// Common finalization code to support custom tp_deallocs. /// - public static void FinalizeObject(ManagedType self) + public static void FinalizeObject(ExtensionType self) { Runtime.PyObject_GC_Del(self.pyHandle); // Not necessary for decref of `tpHandle`. @@ -89,7 +89,7 @@ public static void tp_dealloc(IntPtr ob) { // Clean up a Python instance of this extension type. This // frees the allocated Python object and decrefs the type. - ManagedType self = GetManagedObject(ob); + var self = GetManagedObject(new BorrowedReference(ob)); FinalizeObject(self); } } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 854c32be4..e8ca8b1d3 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -87,32 +87,40 @@ static ObjectOffset() ob_data = (n + 3) * size; } - public static int magic(IntPtr ob) - { - if (ob == IntPtr.Zero) throw new ArgumentNullException(nameof(ob)); - - if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || - (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) - { - return ExceptionOffset.ob_data; - } + public static int GetDefaultGCHandleOffset() => ob_data; - IntPtr tp = Runtime.PyObject_TYPE(ob); - IntPtr metatype = Runtime.PyObject_TYPE(tp); - if (metatype == Runtime.PyCLRMetaType) { - int offset = (int)Marshal.ReadIntPtr(tp, TypeOffset.clr_gchandle_offset); - ClrGcHandleOffsetAssertSanity(offset); - return offset; - } else { - return ob_data; - } + /// + /// Gets GC handle offset in the instances of the specified type + /// + public static int InstanceGCHandle(BorrowedReference type) + { +#if DEBUG + Debug.Assert(ManagedType.IsManagedType(type)); + var meta = Runtime.PyObject_TYPE(type); + if (meta.DangerousGetAddress() != Runtime.PyCLRMetaType) + Debug.Assert(new PyObject(meta).ToString() == ""); +#endif + int offset = (int)Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.clr_gchandle_offset); +#if DEBUG + Debug.Assert(offset < checked((int)Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.tp_basicsize))); +#endif + ClrGcHandleOffsetAssertSanity(offset); + return offset; + } + /// + /// Gets GC handle offset in the instance + /// + public static int ReflectedObjectGCHandle(BorrowedReference reflectedManagedObject) + { + var type = Runtime.PyObject_TYPE(reflectedManagedObject); + return InstanceGCHandle(type); } [Conditional("DEBUG")] static void AssertIsClrType(IntPtr tp) => Debug.Assert(Runtime.PyObject_TYPE(tp) == Runtime.PyCLRMetaType); [Conditional("DEBUG")] internal static void ClrGcHandleOffsetAssertSanity(int offset) - => Debug.Assert(offset > 0 && offset < 1024*1024, "GC handle offset is insane"); + => Debug.Assert(offset > 0 && offset < 1024*4, "GC handle offset is insane"); public static int DictOffset(IntPtr ob) { @@ -131,6 +139,12 @@ public static int Size(IntPtr ob) { return ExceptionOffset.Size(); } + + return PyObject_HEAD_Size(); + } + + public static int PyObject_HEAD_Size() + { #if PYTHON_WITH_PYDEBUG return 6 * IntPtr.Size; #else diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index d01702134..b02c0adee 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -20,23 +20,22 @@ internal abstract class ManagedType /// /// Given a Python object, return the associated managed object or null. /// - [Obsolete("Use GetManagedObject(BorrowedReference)")] - internal static ManagedType GetManagedObject(IntPtr ob) + internal static ManagedType GetManagedObject(BorrowedReference ob) { - if (ob != IntPtr.Zero) + if (!ob.IsNull) { - IntPtr tp = Runtime.PyObject_TYPE(ob); + var tp = Runtime.PyObject_TYPE(ob); if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) { tp = ob; } - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Managed) != 0) + if (IsManagedType(tp)) { - IntPtr op = tp == ob - ? Marshal.ReadIntPtr(tp, TypeOffset.magic()) - : Marshal.ReadIntPtr(ob, ObjectOffset.magic(ob)); + int gcHandleOffset = tp == ob + ? TypeOffset.magic() + : ObjectOffset.ReflectedObjectGCHandle(ob); + IntPtr op = Marshal.ReadIntPtr(ob.DangerousGetAddress(), gcHandleOffset); if (op == IntPtr.Zero) { return null; @@ -48,18 +47,35 @@ internal static ManagedType GetManagedObject(IntPtr ob) return null; } - internal static ManagedType GetManagedObject(BorrowedReference ob) - => ob.IsNull ? null : GetManagedObject(ob.DangerousGetAddress()); + [Obsolete("Use GetManagedObject(BorrowedReference)")] + internal static ManagedType GetManagedObject(IntPtr ob) + => GetManagedObject(new BorrowedReference(ob)); + internal static T GetManagedObject(BorrowedReference ob) + where T : ExtensionType + => (T)GetManagedObject(ob, ObjectOffset.GetDefaultGCHandleOffset()); - internal static ManagedType GetManagedObjectErr(IntPtr ob) + internal static ManagedType GetManagedObject(BorrowedReference ob, int gcHandleOffset) { - ManagedType result = GetManagedObject(ob); - if (result == null) - { - Exceptions.SetError(Exceptions.TypeError, "invalid argument, expected CLR type"); - } - return result; + if (ob.IsNull) throw new ArgumentNullException(nameof(ob)); + ObjectOffset.ClrGcHandleOffsetAssertSanity(gcHandleOffset); + + IntPtr gcHandleValue = Marshal.ReadIntPtr(ob.DangerousGetAddress(), gcHandleOffset); + var gcHandle = (GCHandle)gcHandleValue; + return (ManagedType)gcHandle.Target; } + + /// + /// Checks if specified type is a CLR type + /// + internal static bool IsManagedType(IntPtr tp) + { + var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); + return (flags & TypeFlags.Managed) != 0; + } + + /// Checks if specified type is a CLR type + internal static bool IsManagedType(BorrowedReference type) + => IsManagedType(type.DangerousGetAddress()); } } diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index a2303d293..d7a47317e 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -42,7 +42,7 @@ public MethodBinding(MethodObject m, IntPtr target) : this(m, target, IntPtr.Zer /// public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) { - var self = (MethodBinding)GetManagedObject(tp); + var self = GetInstance(tp); Type[] types = Runtime.PythonArgsToTypeArray(idx); if (types == null) @@ -114,12 +114,15 @@ public int Compare(Type a, Type b) { } } + static MethodBinding GetInstance(IntPtr ob) + => GetManagedObject(new BorrowedReference(ob)); + /// /// MethodBinding __getattribute__ implementation. /// public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { - var self = (MethodBinding)GetManagedObject(ob); + var self = GetInstance(ob); if (!Runtime.PyString_Check(key)) { @@ -162,7 +165,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) /// public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) { - var self = (MethodBinding)GetManagedObject(ob); + var self = GetInstance(ob); // This works around a situation where the wrong generic method is picked, // for example this method in the tests: string Overloaded(int arg1, int arg2, string arg3) @@ -225,12 +228,13 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) IntPtr baseMethod = Runtime.PyObject_GetAttrString(target, baseMethodName); if (baseMethod != IntPtr.Zero) { - var baseSelf = GetManagedObject(baseMethod) as MethodBinding; - if (baseSelf != null) + IntPtr baseMethodType = Runtime.PyObject_TYPE(baseMethod); + IntPtr methodBindingTypeHandle = TypeManager.GetTypeHandle(typeof(MethodBinding)); + if (baseMethodType == methodBindingTypeHandle) { - self = baseSelf; + self = GetInstance(baseMethod); + Runtime.XDecref(baseMethod); } - Runtime.XDecref(baseMethod); } else { @@ -257,7 +261,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) /// public static IntPtr tp_hash(IntPtr ob) { - var self = (MethodBinding)GetManagedObject(ob); + var self = GetInstance(ob); long x = 0; long y = 0; @@ -291,7 +295,7 @@ public static IntPtr tp_hash(IntPtr ob) /// public static IntPtr tp_repr(IntPtr ob) { - var self = (MethodBinding)GetManagedObject(ob); + var self = GetInstance(ob); string type = self.target == IntPtr.Zero ? "unbound" : "bound"; string name = self.m.name; return Runtime.PyString_FromString($"<{type} method '{name}'>"); @@ -302,7 +306,7 @@ public static IntPtr tp_repr(IntPtr ob) /// public new static void tp_dealloc(IntPtr ob) { - var self = (MethodBinding)GetManagedObject(ob); + var self = GetInstance(ob); Runtime.XDecref(self.target); Runtime.XDecref(self.targetType); FinalizeObject(self); diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index 96619a22d..0be75ae4a 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -150,7 +150,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) /// public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { - var self = (MethodObject)GetManagedObject(ds); + var self = GetManagedObject(new BorrowedReference(ds)); MethodBinding binding; // If the method is accessed through its type (rather than via diff --git a/src/runtime/modulefunctionobject.cs b/src/runtime/modulefunctionobject.cs index 8f8692af9..f6321eca9 100644 --- a/src/runtime/modulefunctionobject.cs +++ b/src/runtime/modulefunctionobject.cs @@ -23,7 +23,7 @@ public ModuleFunctionObject(Type type, string name, MethodInfo[] info, bool allo /// public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) { - var self = (ModuleFunctionObject)GetManagedObject(ob); + var self = GetManagedObject(new BorrowedReference(ob)); return self.Invoke(ob, args, kw); } @@ -32,7 +32,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) /// public new static IntPtr tp_repr(IntPtr ob) { - var self = (ModuleFunctionObject)GetManagedObject(ob); + var self = GetManagedObject(new BorrowedReference(ob)); return Runtime.PyString_FromString($""); } } diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index 0a3933005..2d2e3343f 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -251,7 +251,7 @@ internal void InitializeModuleMembers() /// public static IntPtr tp_getattro(IntPtr ob, IntPtr key) { - var self = (ModuleObject)GetManagedObject(ob); + var self = GetManagedObject(new BorrowedReference(ob)); if (!Runtime.PyString_Check(key)) { @@ -301,7 +301,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) /// public static IntPtr tp_repr(IntPtr ob) { - var self = (ModuleObject)GetManagedObject(ob); + var self = GetManagedObject(new BorrowedReference(ob)); return Runtime.PyString_FromString($""); } } diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index f2c97f163..ae8dca15b 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -21,7 +21,8 @@ public PropertyObject(PropertyInfo md) info = md; } - + static PropertyObject GetInstance(IntPtr ob) + => GetManagedObject(new BorrowedReference(ob)); /// /// Descriptor __get__ implementation. This method returns the /// value of the property on the given object. The returned value @@ -29,7 +30,7 @@ public PropertyObject(PropertyInfo md) /// public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { - var self = (PropertyObject)GetManagedObject(ds); + var self = GetInstance(ds); MethodInfo getter = self.getter; object result; @@ -89,7 +90,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) /// public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) { - var self = (PropertyObject)GetManagedObject(ds); + var self = GetInstance(ds); MethodInfo setter = self.setter; object newval; @@ -157,7 +158,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) /// public static IntPtr tp_repr(IntPtr ob) { - var self = (PropertyObject)GetManagedObject(ob); + var self = GetInstance(ob); return Runtime.PyString_FromString($""); } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index c21b7b470..a843bcf9d 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -111,7 +112,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) { string name = GetPythonTypeName(clrType); - int ob_size = ObjectOffset.Size(Runtime.PyTypeType); + int ob_size; int tp_dictoffset = ObjectOffset.DictOffset(Runtime.PyTypeType); // XXX Hack, use a different base class for System.Exception @@ -119,7 +120,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) // subclass BaseException (or better Exception). if (typeof(Exception).IsAssignableFrom(clrType)) { - ob_size = ObjectOffset.Size(Exceptions.Exception); tp_dictoffset = ObjectOffset.DictOffset(Exceptions.Exception); } @@ -141,33 +141,34 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) InitializeSlot(type, TypeOffset.tp_getattro, typeof(SlotOverrides).GetMethod(nameof(SlotOverrides.tp_getattro))); } - int extraTypeDataOffset = ob_size - MetaType.ExtraTypeDataSize; + int extraTypeDataOffset; try { using PyTuple baseTuple = GetBaseTypeTuple(clrType); - if (baseTuple.Length() > 0) - { - IntPtr primaryBase = baseTuple[0].Reference.DangerousIncRefOrNull(); - Marshal.WriteIntPtr(type, TypeOffset.tp_base, primaryBase); + Debug.Assert(baseTuple.Length() > 0); + IntPtr primaryBase = baseTuple[0].Reference.DangerousIncRefOrNull(); + Marshal.WriteIntPtr(type, TypeOffset.tp_base, primaryBase); - if (baseTuple.Length() > 1) { - Marshal.WriteIntPtr(type, TypeOffset.tp_bases, baseTuple.Reference.DangerousIncRefOrNull()); - } + if (baseTuple.Length() > 1) { + Marshal.WriteIntPtr(type, TypeOffset.tp_bases, baseTuple.Reference.DangerousIncRefOrNull()); + } - int baseSize = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.tp_basicsize)); - if (!ClassObject.IsManagedType(primaryBase)) - { - // custom base type is a Python type, so we must allocate additional space for GC handle - extraTypeDataOffset = baseSize; - ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); - ob_size = baseSize + MetaType.ExtraTypeDataSize; - } else - { - extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.clr_gchandle_offset)); - ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); - ob_size = baseSize; - } + int baseSize = primaryBase == Runtime.PyBaseObjectType ? ObjectOffset.PyObject_HEAD_Size() + : primaryBase == Exceptions.Exception ? ExceptionOffset.Size() + : checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.tp_basicsize)); + if (!ManagedType.IsManagedType(primaryBase)) + { + // base type is a Python type, so we must allocate additional space for GC handle + extraTypeDataOffset = baseSize; + ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); + ob_size = baseSize + MetaType.ExtraTypeDataSize; + } else + { + extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.clr_gchandle_offset)); + ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); + ob_size = baseSize; } + Debug.Assert(extraTypeDataOffset > tp_dictoffset); } catch (Exception error) { @@ -282,8 +283,11 @@ static PyTuple GetBaseTypeTuple(Type clrType) var baseOverride = Util.GetLatestAttribute(clrType) ?? BaseTypeAttributeBase.Default; var types = baseOverride.BaseTypes(clrType); - if (types is null) throw new InvalidOperationException(); - if (types.Length() == 0) return new PyTuple(); + if (types is null || types.Length() == 0) + { + throw new InvalidOperationException("At least one base type must be specified"); + } + for (int index = 0; index < types.Length(); index++) { IntPtr baseType = Runtime.PyTuple_GetItem(types.Handle, index); if (!PyType.IsTypeType(baseType)) { From efe6003962e734251fde527021249bba06eb66ca Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 27 Apr 2020 17:29:53 -0700 Subject: [PATCH 136/240] fixed crash in TestPythonExceptionFormatNoError --- src/runtime/NewReference.cs | 9 +++++++++ src/runtime/pythonexception.cs | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs index 6e66232d0..267bcfeda 100644 --- a/src/runtime/NewReference.cs +++ b/src/runtime/NewReference.cs @@ -44,6 +44,15 @@ public void Dispose() public static NewReference DangerousFromPointer(IntPtr pointer) => new NewReference {pointer = pointer}; + public IntPtr DangerousMoveToPointer() + { + if (this.IsNull()) throw new NullReferenceException(); + + var result = this.pointer; + this.pointer = IntPtr.Zero; + return result; + } + [Pure] internal static IntPtr DangerousGetAddress(in NewReference reference) => IsNull(reference) ? throw new NullReferenceException() : reference.pointer; diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index a244f39c0..787d137fd 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -25,9 +25,9 @@ public PythonException() { IntPtr gs = PythonEngine.AcquireLock(); Runtime.PyErr_Fetch(out var type, out var value, out var traceback); - _pyType = type.DangerousGetAddress(); - _pyValue = value.DangerousGetAddress(); - _pyTB = traceback.DangerousGetAddress(); + _pyType = type.IsNull() ? IntPtr.Zero : type.DangerousMoveToPointer(); + _pyValue = value.IsNull() ? IntPtr.Zero : value.DangerousMoveToPointer(); + _pyTB = traceback.IsNull() ? IntPtr.Zero : traceback.DangerousMoveToPointer(); if (_pyType != IntPtr.Zero && _pyValue != IntPtr.Zero) { string message; From b7b1b9ffe753e64f371fde25c16daa36ff076718 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 2 May 2020 19:23:48 -0700 Subject: [PATCH 137/240] make TypeFlags an enum --- src/runtime/clrobject.cs | 2 +- src/runtime/interop.cs | 55 +++++++++++++++++++------------------- src/runtime/managedtype.cs | 2 +- src/runtime/metatype.cs | 6 ++--- src/runtime/typemanager.cs | 12 ++++----- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 31b852f4a..168d08855 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -11,7 +11,7 @@ internal CLRObject(object ob, IntPtr tp) { IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); - long flags = Util.ReadCLong(tp, TypeOffset.tp_flags); + var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) != 0) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.DictOffset(tp)); diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index e8ca8b1d3..aed7a0ce5 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -293,42 +293,43 @@ public static void FreeModuleDef(IntPtr ptr) /// Note that the two values reserved for stackless have been put /// to good use as PythonNet specific flags (Managed and Subclass) /// - internal static class TypeFlags + [Flags] + enum TypeFlags: int { - public static int HeapType = (1 << 9); + HeapType = (1 << 9), /// /// Unless this flag is set, the type can't be inherited from (equivalent to C# sealed) /// - public static int BaseType = (1 << 10); - public static int Ready = (1 << 12); - public static int Readying = (1 << 13); - public static int HaveGC = (1 << 14); + BaseType = (1 << 10), + Ready = (1 << 12), + Readying = (1 << 13), + HaveGC = (1 << 14), // 15 and 16 are reserved for stackless - public static int HaveStacklessExtension = 0; + HaveStacklessExtension = 0, /* XXX Reusing reserved constants */ - public static int Managed = (1 << 15); // PythonNet specific - public static int Subclass = (1 << 16); // PythonNet specific - public static int HaveIndex = (1 << 17); + Managed = (1 << 15), // PythonNet specific + Subclass = (1 << 16), // PythonNet specific + HaveIndex = (1 << 17), /* Objects support nb_index in PyNumberMethods */ - public static int HaveVersionTag = (1 << 18); - public static int ValidVersionTag = (1 << 19); - public static int IsAbstract = (1 << 20); - public static int HaveNewBuffer = (1 << 21); + HaveVersionTag = (1 << 18), + ValidVersionTag = (1 << 19), + IsAbstract = (1 << 20), + HaveNewBuffer = (1 << 21), // TODO: Implement FastSubclass functions - public static int IntSubclass = (1 << 23); - public static int LongSubclass = (1 << 24); - public static int ListSubclass = (1 << 25); - public static int TupleSubclass = (1 << 26); - public static int StringSubclass = (1 << 27); - public static int UnicodeSubclass = (1 << 28); - public static int DictSubclass = (1 << 29); - public static int BaseExceptionSubclass = (1 << 30); - public static int TypeSubclass = (1 << 31); - - - public static int Default = ( + IntSubclass = (1 << 23), + LongSubclass = (1 << 24), + ListSubclass = (1 << 25), + TupleSubclass = (1 << 26), + StringSubclass = (1 << 27), + UnicodeSubclass = (1 << 28), + DictSubclass = (1 << 29), + BaseExceptionSubclass = (1 << 30), + TypeSubclass = (1 << 31), + + + Default = ( HaveStacklessExtension | - HaveVersionTag); + HaveVersionTag), } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index b02c0adee..8d3a00bd5 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -70,7 +70,7 @@ internal static ManagedType GetManagedObject(BorrowedReference ob, int gcHandleO /// internal static bool IsManagedType(IntPtr tp) { - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); + var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); return (flags & TypeFlags.Managed) != 0; } diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 76dc96ee4..fa8beeae1 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -100,13 +100,13 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) return IntPtr.Zero; } - int flags = TypeFlags.Default; + var flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (long)flags); TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc); TypeManager.CopySlot(base_type, type, TypeOffset.clr_gchandle_offset); @@ -239,7 +239,7 @@ public static void tp_dealloc(IntPtr tp) { // Fix this when we dont cheat on the handle for subclasses! - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); + var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) == 0) { IntPtr gc = Marshal.ReadIntPtr(tp, TypeOffset.magic()); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index a843bcf9d..dcfa3b681 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -91,9 +91,9 @@ internal static IntPtr CreateType(Type impl) InitializeSlots(type, impl); - int flags = TypeFlags.Default | TypeFlags.Managed | + var flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (long)flags); if (Runtime.PyType_Ready(type) != 0) throw new PythonEngineException("Can not create type", PythonException.FromPyErr()); @@ -183,12 +183,12 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, (IntPtr)tp_dictoffset); Marshal.WriteIntPtr(type, TypeOffset.clr_gchandle_offset, (IntPtr)extraTypeDataOffset); - int flags = TypeFlags.Default; + var flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (long)flags); // Leverage followup initialization from the Python runtime. Note // that the type of the new type must PyType_Type at the time we @@ -435,11 +435,11 @@ internal static IntPtr CreateMetaType(Type impl) InitializeSlots(type, impl); - int flags = TypeFlags.Default; + var flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (long)flags); // We need space for 3 PyMethodDef structs, each of them // 4 int-ptrs in size. From 144b8c98a72572bf5a893781cc414e8bc3dcebd2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 4 May 2020 14:05:40 -0700 Subject: [PATCH 138/240] removed obsolete IConvertibleToPython and ConvertibleFromPythonAttribute --- src/embed_tests/TestCustomArgMarshal.cs | 68 ------------------- src/runtime/ConvertibleFromPythonAttribute.cs | 23 ------- src/runtime/IConvertibleToPython.cs | 17 ----- src/runtime/converter.cs | 51 -------------- 4 files changed, 159 deletions(-) delete mode 100644 src/runtime/ConvertibleFromPythonAttribute.cs delete mode 100644 src/runtime/IConvertibleToPython.cs diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs index 869809ee9..7c084d7f5 100644 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ b/src/embed_tests/TestCustomArgMarshal.cs @@ -4,8 +4,6 @@ namespace Python.EmbeddingTest { - using Runtime = Python.Runtime.Runtime; - class TestCustomArgMarshal { [OneTimeSetUp] @@ -40,50 +38,6 @@ public void MarshallerOverride() { } Assert.AreEqual(expected: 42, actual: obj.LastArgument); } - - [Test] - public void ConvertibleToPython() { - var obj = new Convertible(convert: true); - int converted; - using (Py.GIL()) { - dynamic identity = PythonEngine.Eval("lambda o: o"); - converted = identity(obj); - } - Assert.AreEqual(expected: Convertible.Value, actual: converted); - } - - [Test] - public void ConvertibleToPythonBypass() { - var obj = new Convertible(convert: false); - Convertible converted; - using (Py.GIL()) { - dynamic identity = PythonEngine.Eval("lambda o: o"); - converted = identity(obj); - } - Assert.AreEqual(expected: obj, actual: converted); - } - - [Test] - public void ConvertibleFromPython() { - using (Py.GIL()) { - bool ok = false; - void Accept(ConvertibleFromPython obj) => ok = true; - dynamic callWithInt = PythonEngine.Eval("lambda f: f(42)"); - callWithInt(new Action(Accept)); - Assert.IsTrue(ok); - } - } - - [Test] - public void ConvertibleFromPythonBypass() { - using (Py.GIL()) { - void Accept(ConvertibleFromPython obj) { } - dynamic callWithInt = PythonEngine.Eval("lambda f: f('42')"); - Assert.Throws(() => - callWithInt(new Action(Accept)), - message: "Python.Runtime.PythonException : TypeError : No method matches given arguments: ()"); - } - } } [PyArgConverter(typeof(CustomArgConverter))] @@ -129,26 +83,4 @@ public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool n return true; } } - - class Convertible : IConvertibleToPython { - public const int Value = 42; - readonly bool convert; - public Convertible(bool convert) { this.convert = convert; } - public PyObject TryConvertToPython() => this.convert ? Value.ToPython() : null; - } - - class ConvertibleAttribute : ConvertibleFromPythonAttribute { - public override bool TryConvertFromPython(PyObject pyObj, out T value) { - if (Runtime.PyString_Check(pyObj.Handle)) { - value = default; - return false; - } - - value = Activator.CreateInstance(); - return true; - } - } - - [Convertible] - class ConvertibleFromPython { } } diff --git a/src/runtime/ConvertibleFromPythonAttribute.cs b/src/runtime/ConvertibleFromPythonAttribute.cs deleted file mode 100644 index 342eb6495..000000000 --- a/src/runtime/ConvertibleFromPythonAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Python.Runtime -{ - /// - /// Base class for all attributes, that override converting Python values to specific types. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct - | AttributeTargets.Enum | AttributeTargets.Delegate, - AllowMultiple = false, - Inherited = true)] - public abstract class ConvertibleFromPythonAttribute: Attribute - { - /// - /// Converts Python object to type . - /// If conversion this converter does not support source or target type, it returns false instead. - /// - /// .NET type to convert Python object to - /// The Python object to convert - /// The variable, that will receive the converted object - public abstract bool TryConvertFromPython(PyObject pyObj, out T value); - } -} diff --git a/src/runtime/IConvertibleToPython.cs b/src/runtime/IConvertibleToPython.cs deleted file mode 100644 index 7d964fbf1..000000000 --- a/src/runtime/IConvertibleToPython.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Python.Runtime -{ - /// - /// Implement this interface to change how instances - /// of your class are presented to Python interpreter. - /// - public interface IConvertibleToPython - { - /// - /// Converts current object to , - /// which can be passed to the Python interpreter. - /// - /// Returns null if conversion should be skipped - /// - PyObject TryConvertToPython(); - } -} diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index c5c52c5c4..405b03c2f 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -123,17 +123,6 @@ internal static IntPtr ToPython(object value, Type type) return handle; } - if (value is IConvertibleToPython convertible) - { - pyObject = convertible.TryConvertToPython(); - if (pyObject != null) - { - IntPtr handle = pyObject.Handle; - Runtime.XIncref(handle); - return handle; - } - } - IntPtr result; // Null always converts to None in Python. @@ -458,12 +447,6 @@ internal static bool ToManagedValue(IntPtr value, Type obType, TypeCode typeCode = Type.GetTypeCode(obType); if (typeCode == TypeCode.Object) { - var converter = TypeConverterCache.GetOrAdd(obType, GetConverter); - if (converter != null && converter(new BorrowedReference(value), out result)) - { - return true; - } - var pyType = new BorrowedReference(Runtime.PyObject_TYPE(value)); if (PyObjectConversions.TryDecode(new BorrowedReference(value), pyType, obType, out result)) { @@ -479,41 +462,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return ToPrimitive(value, obType, out result, setError); } - static TryConvertFromPythonDelegate GetConverter(Type targetType) - { - var converterAttribute = Util.GetLatestAttribute(targetType); - if (converterAttribute == null) - { - return null; - } - - var convert = converterAttribute.GetType() - .GetMethod(nameof(converterAttribute.TryConvertFromPython), - BindingFlags.Instance | BindingFlags.Public); - if (convert == null) - { - throw new NotSupportedException($"The type {converterAttribute.GetType()} must have exactly one public conversion method"); - } - convert = convert.MakeGenericMethod(targetType); - - bool TryConvert(BorrowedReference pyHandle, out object result) { - var pyObj = new PyObject(pyHandle); - var @params = new object[] {pyObj, null}; - bool success = (bool)convert.Invoke(converterAttribute, @params); - if (!success) - { - pyObj.Dispose(); - } - result = @params[1]; - return success; - } - - return TryConvert; - } - internal delegate bool TryConvertFromPythonDelegate(BorrowedReference pyObj, out object result); - static readonly ConcurrentDictionary TypeConverterCache = - new ConcurrentDictionary(); /// /// Convert a Python value to an instance of a primitive managed type. From 9a36164492f381f323f42c7e4e0a4f7cfc97886b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 4 May 2020 14:17:43 -0700 Subject: [PATCH 139/240] removed obsolete IPyArgumentConverter --- .editorconfig | 17 +-- src/embed_tests/TestCustomArgMarshal.cs | 86 ------------- src/runtime/defaultpyargconverter.cs | 111 ----------------- src/runtime/methodbinder.cs | 155 +++++++++++++++--------- src/runtime/pyargconverter.cs | 59 --------- 5 files changed, 106 insertions(+), 322 deletions(-) delete mode 100644 src/embed_tests/TestCustomArgMarshal.cs delete mode 100644 src/runtime/defaultpyargconverter.cs delete mode 100644 src/runtime/pyargconverter.cs diff --git a/.editorconfig b/.editorconfig index 6b907d1f4..2261004d2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -25,10 +25,11 @@ dotnet_sort_system_directives_first = true dotnet_separate_import_directive_groups = true [*.cs] -csharp_new_line_before_open_brace = all -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true +csharp_new_line_before_open_brace = all:suggestion +csharp_new_line_before_else = true:suggestion +csharp_new_line_before_catch = true:suggestion +csharp_new_line_before_finally = true:suggesion +csharp_prefer_braces = true:suggestion # Solution [*.sln] @@ -38,11 +39,3 @@ indent_style = tab [.bumpversion.cfg] trim_trailing_whitespace = false indent_style = tab - -[*.cs] -csharp_new_line_before_open_brace = true:suggestion -csharp_new_line_before_else = true:suggestion -csharp_new_line_before_catch = true:suggestion -csharp_new_line_before_finally = true:suggestion - -csharp_prefer_braces = true:suggestion diff --git a/src/embed_tests/TestCustomArgMarshal.cs b/src/embed_tests/TestCustomArgMarshal.cs deleted file mode 100644 index 7c084d7f5..000000000 --- a/src/embed_tests/TestCustomArgMarshal.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - class TestCustomArgMarshal - { - [OneTimeSetUp] - public void SetUp() - { - PythonEngine.Initialize(); - } - - [OneTimeTearDown] - public void Dispose() - { - PythonEngine.Shutdown(); - } - - [Test] - public void CustomArgMarshaller() - { - var obj = new CustomArgMarshaling(); - using (Py.GIL()) { - dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallWithInt('42')"); - callWithInt(obj.ToPython()); - } - Assert.AreEqual(expected: 42, actual: obj.LastArgument); - } - - [Test] - public void MarshallerOverride() { - var obj = new DerivedMarshaling(); - using (Py.GIL()) { - dynamic callWithInt = PythonEngine.Eval("lambda o: o.CallWithInt({ 'value': 42 })"); - callWithInt(obj.ToPython()); - } - Assert.AreEqual(expected: 42, actual: obj.LastArgument); - } - } - - [PyArgConverter(typeof(CustomArgConverter))] - class CustomArgMarshaling { - public object LastArgument { get; protected set; } - public virtual void CallWithInt(int value) => this.LastArgument = value; - } - - // this should override original custom marshaling behavior for any new methods - [PyArgConverter(typeof(CustomArgConverter2))] - class DerivedMarshaling : CustomArgMarshaling { - public override void CallWithInt(int value) { - base.CallWithInt(value); - } - } - - class CustomArgConverter : DefaultPyArgumentConverter { - public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, - out object arg, out bool isOut) { - if (parameterType != typeof(int)) - return base.TryConvertArgument(pyarg, parameterType, needsResolution, out arg, out isOut); - bool isString = base.TryConvertArgument(pyarg, typeof(string), needsResolution, - out arg, out isOut); - if (!isString) return false; - int number; - if (!int.TryParse((string)arg, out number)) return false; - arg = number; - return true; - } - } - - class CustomArgConverter2 : DefaultPyArgumentConverter { - public override bool TryConvertArgument(IntPtr pyarg, Type parameterType, bool needsResolution, - out object arg, out bool isOut) { - if (parameterType != typeof(int)) - return base.TryConvertArgument(pyarg, parameterType, needsResolution, out arg, out isOut); - bool isPyObject = base.TryConvertArgument(pyarg, typeof(PyObject), needsResolution, - out arg, out isOut); - if (!isPyObject) return false; - var dict = new PyDict((PyObject)arg); - int number = (dynamic)dict["value"]; - arg = number; - return true; - } - } -} diff --git a/src/runtime/defaultpyargconverter.cs b/src/runtime/defaultpyargconverter.cs deleted file mode 100644 index b2dd5d236..000000000 --- a/src/runtime/defaultpyargconverter.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace Python.Runtime { - using System; - - /// - /// The implementation of used by default - /// - public class DefaultPyArgumentConverter: IPyArgumentConverter - { - /// - /// Gets the singleton instance. - /// - public static DefaultPyArgumentConverter Instance { get; } = new DefaultPyArgumentConverter(); - - /// - /// - /// Attempts to convert an argument passed by Python to the specified parameter type. - /// - /// Unmanaged pointer to the Python argument value - /// The expected type of the parameter - /// true if the method is overloaded - /// This parameter will receive the converted value, matching the specified type - /// This parameter will be set to true, - /// if the final type needs to be marshaled as an out argument. - /// true, if the object matches requested type, - /// and conversion was successful, otherwise false - public virtual bool TryConvertArgument( - IntPtr pyarg, Type parameterType, bool needsResolution, - out object arg, out bool isOut) - { - arg = null; - isOut = false; - Type clrType = TryComputeClrArgumentType(parameterType, pyarg, needsResolution: needsResolution); - if (clrType == null) - { - return false; - } - - if (!Converter.ToManaged(pyarg, clrType, out arg, false)) - { - Exceptions.Clear(); - return false; - } - - isOut = clrType.IsByRef; - return true; - } - - static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) - { - // this logic below handles cases when multiple overloading methods - // are ambiguous, hence comparison between Python and CLR types - // is necessary - Type clrType = null; - IntPtr pyArgType; - if (needsResolution) - { - // HACK: each overload should be weighted in some way instead - pyArgType = Runtime.PyObject_Type(argument); - Exceptions.Clear(); - if (pyArgType != IntPtr.Zero) - { - clrType = Converter.GetTypeByAlias(pyArgType); - } - Runtime.XDecref(pyArgType); - } - - if (clrType != null) - { - if ((parameterType != typeof(object)) && (parameterType != clrType)) - { - IntPtr pyParamType = Converter.GetPythonTypeByAlias(parameterType); - pyArgType = Runtime.PyObject_Type(argument); - Exceptions.Clear(); - - bool typeMatch = false; - if (pyArgType != IntPtr.Zero && pyParamType == pyArgType) - { - typeMatch = true; - clrType = parameterType; - } - if (!typeMatch) - { - // this takes care of enum values - TypeCode argTypeCode = Type.GetTypeCode(parameterType); - TypeCode paramTypeCode = Type.GetTypeCode(clrType); - if (argTypeCode == paramTypeCode) - { - typeMatch = true; - clrType = parameterType; - } - } - Runtime.XDecref(pyArgType); - if (!typeMatch) - { - return null; - } - } - else - { - clrType = parameterType; - } - } - else - { - clrType = parameterType; - } - - return clrType; - } - } -} diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 86ebb2cf2..21f8391a3 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -21,7 +21,6 @@ internal class MethodBinder public MethodBase[] methods; public bool init = false; public bool allow_threads = true; - IPyArgumentConverter pyArgumentConverter; internal MethodBinder() { @@ -168,50 +167,11 @@ internal MethodBase[] GetMethods() // I'm sure this could be made more efficient. list.Sort(new MethodSorter()); methods = (MethodBase[])list.ToArray(typeof(MethodBase)); - pyArgumentConverter = GetArgumentConverter(this.methods); init = true; } return methods; } - static IPyArgumentConverter GetArgumentConverter(IEnumerable methods) { - IPyArgumentConverter converter = null; - Type converterType = null; - foreach (MethodBase method in methods) - { - PyArgConverterAttribute attribute = TryGetArgConverter(method.DeclaringType); - if (converterType == null) - { - if (attribute == null) continue; - - converterType = attribute.ConverterType; - converter = attribute.Converter; - } else if (converterType != attribute?.ConverterType) - { - throw new NotSupportedException("All methods must have the same IPyArgumentConverter"); - } - } - - return converter ?? DefaultPyArgumentConverter.Instance; - } - - static readonly ConcurrentDictionary ArgConverterCache = - new ConcurrentDictionary(); - static PyArgConverterAttribute TryGetArgConverter(Type type) { - if (type == null) return null; - - return ArgConverterCache.GetOrAdd(type, declaringType => - declaringType - .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: true) - .OfType() - .SingleOrDefault() - ?? declaringType.Assembly - .GetCustomAttributes(typeof(PyArgConverterAttribute), inherit: true) - .OfType() - .SingleOrDefault() - ); - } - /// /// Precedence algorithm largely lifted from Jython - the concerns are /// generally the same so we'll start with this and tweak as necessary. @@ -343,17 +303,14 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth var pynargs = (int)Runtime.PyTuple_Size(args); var isGeneric = false; - IPyArgumentConverter argumentConverter; if (info != null) { _methods = new MethodBase[1]; _methods.SetValue(info, 0); - argumentConverter = GetArgumentConverter(_methods); } else { _methods = GetMethods(); - argumentConverter = this.pyArgumentConverter; } // TODO: Clean up @@ -372,7 +329,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth continue; } var outs = 0; - var margs = TryConvertArguments(pi, paramsArray, argumentConverter, args, pynargs, kwargDict, defaultArgList, + var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList, needsResolution: _methods.Length > 1, outs: out outs); @@ -421,7 +378,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth /// /// Information about expected parameters /// true, if the last parameter is a params array. - /// Converter, that will be used to convert marshal arguments to .NET /// A pointer to the Python argument tuple /// Number of arguments, passed by Python /// Dictionary of keyword argument name to python object pointer @@ -430,7 +386,6 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth /// Returns number of output parameters /// An array of .NET arguments, that can be passed to a method. static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, - IPyArgumentConverter argumentConverter, IntPtr args, int pyArgCount, Dictionary kwargDict, ArrayList defaultArgList, @@ -440,12 +395,15 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, outs = 0; var margs = new object[pi.Length]; int arrayStart = paramsArray ? pi.Length - 1 : -1; - for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) { + for (int paramIndex = 0; paramIndex < pi.Length; paramIndex++) + { var parameter = pi[paramIndex]; bool hasNamedParam = kwargDict.ContainsKey(parameter.Name); - if (paramIndex >= pyArgCount && !hasNamedParam) { - if (defaultArgList != null) { + if (paramIndex >= pyArgCount && !hasNamedParam) + { + if (defaultArgList != null) + { margs[paramIndex] = defaultArgList[paramIndex - pyArgCount]; } @@ -453,9 +411,12 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, } IntPtr op; - if (hasNamedParam) { + if (hasNamedParam) + { op = kwargDict[parameter.Name]; - } else { + } + else + { op = (arrayStart == paramIndex) // map remaining Python arguments to a tuple since // the managed function accepts it - hopefully :] @@ -464,18 +425,20 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, } bool isOut; - if (!argumentConverter.TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { + if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { return null; } - if (arrayStart == paramIndex) { + if (arrayStart == paramIndex) + { // TODO: is this a bug? Should this happen even if the conversion fails? // GetSlice() creates a new reference but GetItem() // returns only a borrow reference. Runtime.XDecref(op); } - if (parameter.IsOut || isOut) { + if (parameter.IsOut || isOut) + { outs++; } } @@ -483,6 +446,90 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, return margs; } + static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, + out object arg, out bool isOut) + { + arg = null; + isOut = false; + var clrtype = TryComputeClrArgumentType(parameterType, op, needsResolution: needsResolution); + if (clrtype == null) + { + return false; + } + + if (!Converter.ToManaged(op, clrtype, out arg, false)) + { + Exceptions.Clear(); + return false; + } + + isOut = clrtype.IsByRef; + return true; + } + + static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) + { + // this logic below handles cases when multiple overloading methods + // are ambiguous, hence comparison between Python and CLR types + // is necessary + Type clrtype = null; + IntPtr pyoptype; + if (needsResolution) + { + // HACK: each overload should be weighted in some way instead + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + if (pyoptype != IntPtr.Zero) + { + clrtype = Converter.GetTypeByAlias(pyoptype); + } + Runtime.XDecref(pyoptype); + } + + if (clrtype != null) + { + if ((parameterType != typeof(object)) && (parameterType != clrtype)) + { + IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType); + pyoptype = Runtime.PyObject_Type(argument); + Exceptions.Clear(); + + bool typematch = false; + if (pyoptype != IntPtr.Zero && pytype == pyoptype) + { + typematch = true; + clrtype = parameterType; + } + if (!typematch) + { + // this takes care of enum values + TypeCode argtypecode = Type.GetTypeCode(parameterType); + TypeCode paramtypecode = Type.GetTypeCode(clrtype); + if (argtypecode == paramtypecode) + { + typematch = true; + clrtype = parameterType; + } + } + Runtime.XDecref(pyoptype); + if (!typematch) + { + return null; + } + } + else + { + clrtype = parameterType; + } + } + else + { + clrtype = parameterType; + } + + return clrtype; + } + static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] parameters, Dictionary kwargDict, out bool paramsArray, diff --git a/src/runtime/pyargconverter.cs b/src/runtime/pyargconverter.cs deleted file mode 100644 index cf6be7b6d..000000000 --- a/src/runtime/pyargconverter.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace Python.Runtime { - using System; - - /// - /// Specifies how to convert Python objects, passed to .NET functions to the expected CLR types. - /// - public interface IPyArgumentConverter - { - /// - /// Attempts to convert an argument passed by Python to the specified parameter type. - /// - /// Unmanaged pointer to the Python argument value - /// The expected type of the parameter - /// true if the method is overloaded - /// This parameter will receive the converted value, matching the specified type - /// This parameter will be set to true, - /// if the final type needs to be marshaled as an out argument. - /// true, if the object matches requested type, - /// and conversion was successful, otherwise false - bool TryConvertArgument(IntPtr pyarg, Type parameterType, - bool needsResolution, out object arg, out bool isOut); - } - - /// - /// Specifies an argument converter to be used, when methods in this class/assembly are called from Python. - /// - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct)] - public class PyArgConverterAttribute : Attribute - { - static readonly Type[] EmptyArgTypeList = new Type[0]; - static readonly object[] EmptyArgList = new object[0]; - - /// - /// Gets the instance of the converter, that will be used when calling methods - /// of this class/assembly from Python - /// - public IPyArgumentConverter Converter { get; } - /// - /// Gets the type of the converter, that will be used when calling methods - /// of this class/assembly from Python - /// - public Type ConverterType { get; } - - /// - /// Specifies an argument converter to be used, when methods - /// in this class/assembly are called from Python. - /// - /// Type of the converter to use. - /// Must implement . - public PyArgConverterAttribute(Type converterType) - { - if (converterType == null) throw new ArgumentNullException(nameof(converterType)); - var ctor = converterType.GetConstructor(EmptyArgTypeList); - if (ctor == null) throw new ArgumentException("Specified converter must have public parameterless constructor"); - this.Converter = (IPyArgumentConverter)ctor.Invoke(EmptyArgList); - this.ConverterType = converterType; - } - } -} From c9b3e835fb5ce49d390013795755500993476ba2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 16:30:16 -0700 Subject: [PATCH 140/240] disable OverloadResolution_BaseOrDerived test --- src/embed_tests/TestInstanceWrapping.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 2bf3e3fb3..0638bf821 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -90,6 +90,7 @@ public void OverloadResolution_ObjOrClass() { } [Test] + [Ignore("Overload resolution does not correctly choose from base vs derived class")] public void OverloadResolution_BaseOrDerived() { var overloaded = new Overloaded(); using (Py.GIL()) { From 4f7d14c001646064597d9080b0ee577ba87e9db6 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 16:35:21 -0700 Subject: [PATCH 141/240] added GitHub actions CI --- .github/workflows/build+test.yml | 32 ++++++++++++++++++++++++++++++++ pythonnet.15.sln | 1 + 2 files changed, 33 insertions(+) create mode 100644 .github/workflows/build+test.yml diff --git a/.github/workflows/build+test.yml b/.github/workflows/build+test.yml new file mode 100644 index 000000000..c1c5dbef3 --- /dev/null +++ b/.github/workflows/build+test.yml @@ -0,0 +1,32 @@ +name: Build + Test + +on: + push: + branches: + - losttech/master + pull_request: + branches: + - losttech/master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.5, 3.7] + steps: + - uses: actions/checkout@v2 + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.1.101 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Build + run: dotnet build src/runtime/Python.Runtime.15.csproj --configuration Release + - name: Test + run: dotnet test src/embed_tests/Python.EmbeddingTest.15.csproj --configuration Release + env: + PYTHON_VERSION: ${{ matrix.python-version }} diff --git a/pythonnet.15.sln b/pythonnet.15.sln index 4c7201399..12ccd4634 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -28,6 +28,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI", "CI", "{D301657F-5EAF- appveyor.yml = appveyor.yml ci\appveyor_build_recipe.ps1 = ci\appveyor_build_recipe.ps1 ci\appveyor_run_tests.ps1 = ci\appveyor_run_tests.ps1 + .github\workflows\build+test.yml = .github\workflows\build+test.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{57F5D701-F265-4736-A5A2-07249E7A4DA3}" From 14d1872dc3ce67db82dce3f7874b4632ab66a2e2 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 16:50:24 -0700 Subject: [PATCH 142/240] added package reference to .NET Framework Reference Assemblies to enable non-Windows build --- src/runtime/Python.Runtime.15.csproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 43492eb9e..4d00136b8 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net40 AnyCPU @@ -72,6 +72,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive From 403e81e96e3774f4ee1064abb9c753b0de40253e Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 17:09:51 -0700 Subject: [PATCH 143/240] retarget EmbeddingTest to .NET Core 3.1 LTS --- src/embed_tests/Python.EmbeddingTest.15.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index 0ed312871..3c4249cbf 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.1 x64;x86 Exe false From 1a339b92307ef8e77d01329db07628e466019598 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 17:19:03 -0700 Subject: [PATCH 144/240] configure python environment for tests --- src/embed_tests/GlobalTestsSetup.cs | 61 +++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/GlobalTestsSetup.cs b/src/embed_tests/GlobalTestsSetup.cs index 458ab6a99..30f9e69c0 100644 --- a/src/embed_tests/GlobalTestsSetup.cs +++ b/src/embed_tests/GlobalTestsSetup.cs @@ -1,14 +1,69 @@ -using NUnit.Framework; -using Python.Runtime; - namespace Python.EmbeddingTest { + using System; + using System.IO; + using System.Runtime.InteropServices; + + using NUnit.Framework; + using Python.Runtime; // As the SetUpFixture, the OneTimeTearDown of this class is executed after // all tests have run. [SetUpFixture] public class GlobalTestsSetup { + [OneTimeSetUp] + public void ConfigureRuntime() + { + if (Path.IsPathFullyQualified(Runtime.PythonDLL)) return; + + string pyVer = Environment.GetEnvironmentVariable("PYTHON_VERSION"); + if (!string.IsNullOrEmpty(pyVer)) + { + Runtime.PythonVersion = Version.Parse(pyVer); + } + + string pyHome = Environment.GetEnvironmentVariable("PYTHON_HOME") + // defined in GitHub action setup-python + ?? Environment.GetEnvironmentVariable("pythonLocation"); + if (!string.IsNullOrEmpty(pyHome)) + { + string dll = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? Path.Combine(pyHome, Runtime.PythonDLL) + : Path.Combine(pyHome, "lib", Runtime.PythonDLL); + if (File.Exists(dll)) + { + Runtime.PythonDLL = dll; + } + } + + if (!Path.IsPathFullyQualified(Runtime.PythonDLL)) + { + string[] paths = Environment.GetEnvironmentVariable("PATH") + .Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries); + foreach (string pathDir in paths) + { + string dll = Path.Combine(pathDir, Runtime.PythonDLL); + if (File.Exists(dll)) + { + Runtime.PythonDLL = dll; + if (string.IsNullOrEmpty(pyHome)) + { + pyHome = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + // on Windows, paths is PYTHON_HOME/dll + ? Path.GetDirectoryName(dll) + // on *nix the path is HOME/lib/dll + : Path.GetDirectoryName(Path.GetDirectoryName(dll)); + } + + break; + } + } + } + + Environment.SetEnvironmentVariable("PYTHON_HOME", pyHome); + } + [OneTimeTearDown] public void FinalCleanup() { From e077e100ee3a691f1018de1be85897ebd9fd78a3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 12 May 2020 17:34:26 -0700 Subject: [PATCH 145/240] updated README badges for Lost Tech fork --- README.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index ee6573d84..33e93c32a 100644 --- a/README.rst +++ b/README.rst @@ -3,9 +3,9 @@ pythonnet - Python for .NET |Join the chat at https://gitter.im/pythonnet/pythonnet| -|appveyor shield| |travis shield| |codecov shield| +|github test shield| -|license shield| |pypi package version| |conda-forge version| |python supported shield| +|license shield| |nuget version| |stackexchange shield| Python for .NET is a package that gives Python programmers nearly @@ -121,6 +121,9 @@ Some features are disabled in Python 3.8.0 because of :target: http://stackoverflow.com/questions/tagged/python.net .. |conda-forge version| image:: https://img.shields.io/conda/vn/conda-forge/pythonnet.svg :target: https://anaconda.org/conda-forge/pythonnet +.. |github test shield| image:: https://github.com/losttech/pythonnet/workflows/Build%20%2B%20Test/badge.svg +.. |nuget version| image:: https://img.shields.io/nuget/vpre/Python.Runtime.UnofficialNetStandard + :target: https://www.nuget.org/packages/Python.Runtime.UnofficialNetStandard/ Resources --------- From d73f623a1d73bc24235c97d7459d0684c32f0550 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 11:00:54 -0700 Subject: [PATCH 146/240] make GlobalTestsSetup partial to enable local configuration --- src/embed_tests/GlobalTestsSetup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/embed_tests/GlobalTestsSetup.cs b/src/embed_tests/GlobalTestsSetup.cs index 30f9e69c0..b3261bd0c 100644 --- a/src/embed_tests/GlobalTestsSetup.cs +++ b/src/embed_tests/GlobalTestsSetup.cs @@ -10,7 +10,7 @@ namespace Python.EmbeddingTest // As the SetUpFixture, the OneTimeTearDown of this class is executed after // all tests have run. [SetUpFixture] - public class GlobalTestsSetup + public partial class GlobalTestsSetup { [OneTimeSetUp] public void ConfigureRuntime() From 901ebc19f43e056dee9b9cc5e673e118057a05b5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 11:01:28 -0700 Subject: [PATCH 147/240] disabled default list conversions --- src/runtime/converter.cs | 42 ---------------------------------------- 1 file changed, 42 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 405b03c2f..c9ad079ff 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -143,22 +143,6 @@ internal static IntPtr ToPython(object value, Type type) } } - if (value is IList && !(value is INotifyPropertyChanged) && value.GetType().IsGenericType) - { - using (var resultlist = new PyList()) - { - foreach (object o in (IEnumerable)value) - { - using (var p = new PyObject(ToPython(o, o?.GetType()))) - { - resultlist.Append(p); - } - } - Runtime.XIncref(resultlist.Handle); - return resultlist.Handle; - } - } - // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. var pyderived = value as IPythonDerivedType; @@ -239,21 +223,6 @@ internal static IntPtr ToPython(object value, Type type) return Runtime.PyLong_FromUnsignedLongLong((ulong)value); default: - if (value is IEnumerable) - { - using (var resultlist = new PyList()) - { - foreach (object o in (IEnumerable)value) - { - using (var p = new PyObject(ToPython(o, o?.GetType()))) - { - resultlist.Append(p); - } - } - Runtime.XIncref(resultlist.Handle); - return resultlist.Handle; - } - } result = CLRObject.GetInstHandle(value, type); return result; } @@ -387,11 +356,6 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return true; } - if (Runtime.PySequence_Check(value)) - { - return ToArray(value, typeof(object[]), out result, setError); - } - Runtime.XIncref(value); // PyObject() assumes ownership result = new PyObject(value); return true; @@ -430,12 +394,6 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return true; } - if (value == Runtime.PyListType || value == Runtime.PyTupleType) - { - result = typeof(object[]); - return true; - } - if (setError) { Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Type"); From dc570e29e0d72fbed0debff38927dc63022eef82 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 11:06:30 -0700 Subject: [PATCH 148/240] replace PyList(PyObject) constructor with explicit Wrap method --- src/embed_tests/TestPyList.cs | 8 ++++---- src/runtime/pylist.cs | 35 +++++++++++++++++++--------------- src/runtime/pysequence.cs | 1 + src/runtime/pythonexception.cs | 2 +- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/embed_tests/TestPyList.cs b/src/embed_tests/TestPyList.cs index e9acfbb45..f3f9242fe 100644 --- a/src/embed_tests/TestPyList.cs +++ b/src/embed_tests/TestPyList.cs @@ -78,22 +78,22 @@ public void TestPyObjectArrayCtor() } [Test] - public void TestPyObjectCtor() + public void TestWrap() { var a = new PyList(); - var s = new PyList(a); + var s = PyList.Wrap(a); Assert.IsInstanceOf(typeof(PyList), s); Assert.AreEqual(0, s.Length()); } [Test] - public void TestBadPyObjectCtor() + public void TestBadWrapArgument() { var i = new PyInt(5); PyList t = null; - var ex = Assert.Throws(() => t = new PyList(i)); + var ex = Assert.Throws(() => t = PyList.Wrap(i)); Assert.AreEqual("object is not a list", ex.Message); Assert.IsNull(t); diff --git a/src/runtime/pylist.cs b/src/runtime/pylist.cs index db741fdc4..2da90d027 100644 --- a/src/runtime/pylist.cs +++ b/src/runtime/pylist.cs @@ -10,6 +10,22 @@ namespace Python.Runtime /// public class PyList : PySequence { + /// + /// Gets an instance of representing the same object as the given object. + /// + public static PyList Wrap(PyObject o) + { + if (o is null) + { + throw new ArgumentNullException(nameof(o)); + } + if (!IsListType(o)) + { + throw new ArgumentException("object is not a list"); + } + return new PyList(o.Reference); + } + /// /// PyList Constructor /// @@ -22,36 +38,25 @@ public PyList(IntPtr ptr) : base(ptr) { } - /// /// PyList Constructor /// /// - /// Copy constructor - obtain a PyList from a generic PyObject. An - /// ArgumentException will be thrown if the given object is not a - /// Python list object. + /// Creates a new PyList from an existing object reference. + /// The object reference is not checked for type-correctness. /// - public PyList(PyObject o) + internal PyList(BorrowedReference reference) : base(reference) { - if (!IsListType(o)) - { - throw new ArgumentException("object is not a list"); - } - Runtime.XIncref(o.obj); - obj = o.obj; } - /// /// PyList Constructor /// /// /// Creates a new empty Python list object. /// - public PyList() + public PyList(): base(Exceptions.ErrorCheck(Runtime.PyList_New(0))) { - obj = Runtime.PyList_New(0); - Exceptions.ErrorCheck(obj); } diff --git a/src/runtime/pysequence.cs b/src/runtime/pysequence.cs index 846b65525..5010531c4 100644 --- a/src/runtime/pysequence.cs +++ b/src/runtime/pysequence.cs @@ -15,6 +15,7 @@ public class PySequence : PyObject, IEnumerable public PySequence(IntPtr ptr) : base(ptr) { } + internal PySequence(BorrowedReference reference) : base(reference) { } [Obsolete] protected PySequence() diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 787d137fd..cb1fd2edb 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -182,7 +182,7 @@ static string TracebackHandleToString(BorrowedReference tracebackHandle) { PyObject tracebackModule = PythonEngine.ImportModule("traceback"); using var traceback = new PyObject(tracebackHandle); - PyList stackLines = new PyList(tracebackModule.InvokeMethod("format_tb", traceback)); + PyList stackLines = PyList.Wrap(tracebackModule.InvokeMethod("format_tb", traceback)); stackLines.Reverse(); var result = new StringBuilder(); foreach (object stackLine in stackLines) { From 35f1313d47fb26c3cc2ddcfc23c6f6db1f89bb0c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 12:54:54 -0700 Subject: [PATCH 149/240] do not dispose python type passed to CanDecode, as user might cache it --- src/runtime/converterextensions.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index 07616ae39..2996d8499 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -125,13 +125,11 @@ internal static bool TryDecode(BorrowedReference obj, BorrowedReference objType, static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type targetType) { IPyObjectDecoder decoder; - using (var pyType = new PyObject(Runtime.SelfIncRef(sourceType))) + var pyType = new PyObject(Runtime.SelfIncRef(sourceType)); + lock (decoders) { - lock (decoders) - { - decoder = decoders.GetDecoder(pyType, targetType); - if (decoder == null) return null; - } + decoder = decoders.GetDecoder(pyType, targetType); + if (decoder == null) return null; } var decode = genericDecode.MakeGenericMethod(targetType); From 8d97d956a1ae0612af59819a2bca38f1a1fa637c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 15:45:59 -0700 Subject: [PATCH 150/240] fixed crash in Iterator.tp_iternext --- src/runtime/iterator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/iterator.cs b/src/runtime/iterator.cs index f9cf10178..0c749df53 100644 --- a/src/runtime/iterator.cs +++ b/src/runtime/iterator.cs @@ -22,7 +22,7 @@ public Iterator(IEnumerator e) /// public static IntPtr tp_iternext(IntPtr ob) { - var self = GetManagedObject(ob) as Iterator; + var self = GetManagedObject(new BorrowedReference(ob)); try { if (!self.iter.MoveNext()) From a024d91a1a99abfcd64b6ed4a6d9556695b7a4ef Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 19:03:05 -0700 Subject: [PATCH 151/240] replaced BaseTypeAttribute mechanism with IPythonBaseTypeProvider --- src/embed_tests/CallableObject.cs | 12 ++++---- src/embed_tests/Inheritance.cs | 29 ++++++++--------- src/embed_tests/TestInstanceWrapping.cs | 4 ++- src/runtime/BaseTypeAttributeBase.cs | 35 --------------------- src/runtime/CoreBaseTypeProvider.cs | 36 ++++++++++++++++++++++ src/runtime/IPythonBaseTypeProvider.cs | 14 +++++++++ src/runtime/InteropConfiguration.cs | 21 +++++++++++++ src/runtime/PythonBaseTypeProviderGroup.cs | 24 +++++++++++++++ src/runtime/Util.cs | 32 ------------------- src/runtime/pythonengine.cs | 15 +++++++++ src/runtime/typemanager.cs | 25 ++++++--------- 11 files changed, 144 insertions(+), 103 deletions(-) delete mode 100644 src/runtime/BaseTypeAttributeBase.cs create mode 100644 src/runtime/CoreBaseTypeProvider.cs create mode 100644 src/runtime/IPythonBaseTypeProvider.cs create mode 100644 src/runtime/InteropConfiguration.cs create mode 100644 src/runtime/PythonBaseTypeProviderGroup.cs diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index bbdf1b21b..76b93c62e 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -12,7 +12,8 @@ public void SetUp() { using (Py.GIL()) { using var locals = new PyDict(); PythonEngine.Exec(CallViaInheritance.BaseClassSource, locals: locals.Handle); - CustomBaseTypeAttribute.BaseClass = locals[CallViaInheritance.BaseClassName]; + CustomBaseTypeProvider.BaseClass = locals[CallViaInheritance.BaseClassName]; + PythonEngine.InteropConfiguration.PythonBaseTypeProviders.Add(new CustomBaseTypeProvider()); } } @@ -43,7 +44,6 @@ class Doubler { class DerivedDoubler : Doubler { } - [CustomBaseType] class CallViaInheritance { public const string BaseClassName = "Forwarder"; public static readonly string BaseClassSource = $@" @@ -56,14 +56,14 @@ class {BaseClassName}(MyCallableBase): pass public int Call(int arg) => 3 * arg; } - class CustomBaseTypeAttribute : BaseTypeAttributeBase { + class CustomBaseTypeProvider : IPythonBaseTypeProvider { internal static PyObject BaseClass; - public override PyTuple BaseTypes(Type type) { + public IEnumerable GetBaseTypes(Type type, IList existingBases) { Assert.Greater(BaseClass.Refcount, 0); return type != typeof(CallViaInheritance) - ? base.BaseTypes(type) - : PyTuple.FromSingleElement(BaseClass); + ? existingBases + : new []{BaseClass}; } } } diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index 27e728871..109486af8 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -11,7 +11,10 @@ public void SetUp() { using (Py.GIL()) { var locals = new PyDict(); PythonEngine.Exec(InheritanceTestBaseClassWrapper.ClassSourceCode, locals: locals.Handle); - CustomBaseTypeAttribute.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + CustomBaseTypeProvider.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + var baseTypeProviders = PythonEngine.InteropConfiguration.PythonBaseTypeProviders; + baseTypeProviders.Add(new CustomBaseTypeProvider()); + baseTypeProviders.Add(new NoEffectBaseTypeProvider()); } } @@ -24,7 +27,7 @@ public void Dispose() { public void IsInstance() { using (Py.GIL()) { var inherited = new Inherited(); - bool properlyInherited = PyIsInstance(inherited, CustomBaseTypeAttribute.BaseClass); + bool properlyInherited = PyIsInstance(inherited, CustomBaseTypeProvider.BaseClass); Assert.IsTrue(properlyInherited); } } @@ -34,7 +37,7 @@ public void IsInstance() { [Test] public void InheritedClassIsNew() { using (Py.GIL()) { - PyObject a = CustomBaseTypeAttribute.BaseClass; + PyObject a = CustomBaseTypeProvider.BaseClass; var inherited = new Inherited(); dynamic getClass = PythonEngine.Eval("lambda o: o.__class__"); PyObject inheritedClass = getClass(inherited); @@ -64,7 +67,7 @@ public void InheritedFromInheritedIsInstance() { scope.Exec($"class B({nameof(Inherited)}): pass"); PyObject b = scope.Eval("B"); PyObject bInst = ((dynamic)b)(scope); - bool properlyInherited = PyIsInstance(bInst, CustomBaseTypeAttribute.BaseClass); + bool properlyInherited = PyIsInstance(bInst, CustomBaseTypeProvider.BaseClass); Assert.IsTrue(properlyInherited); } } @@ -103,26 +106,24 @@ public void PythonCanSetAdHocAttributes() { } } - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - class CustomBaseTypeAttribute : BaseTypeAttributeBase { + class CustomBaseTypeProvider : IPythonBaseTypeProvider { internal static PyObject BaseClass; - public override PyTuple BaseTypes(Type type) + public IEnumerable GetBaseTypes(Type type, IList existingBases) => type != typeof(InheritanceTestBaseClassWrapper) - ? base.BaseTypes(type) - : new PyTuple(new []{ PyType.Get(type.BaseType), BaseClass }); + ? existingBases + : new []{ PyType.Get(type.BaseType), BaseClass }; } - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - class DefaultBaseTypeAttribute : BaseTypeAttributeBase { - + class NoEffectBaseTypeProvider : IPythonBaseTypeProvider + { + public IEnumerable GetBaseTypes(Type type, IList existingBases) + => existingBases; } - [DefaultBaseType] public class PythonWrapperBase { public string WrapperBaseMethod() => nameof(WrapperBaseMethod); } - [CustomBaseType] public class InheritanceTestBaseClassWrapper : PythonWrapperBase { public const string ClassName = "InheritanceTestBaseClass"; public const string ClassSourceCode = "class " + ClassName + diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 0638bf821..202288750 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -12,7 +12,9 @@ public void SetUp() { using (Py.GIL()) { var locals = new PyDict(); PythonEngine.Exec(InheritanceTestBaseClassWrapper.ClassSourceCode, locals: locals.Handle); - CustomBaseTypeAttribute.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + CustomBaseTypeProvider.BaseClass = locals[InheritanceTestBaseClassWrapper.ClassName]; + var baseTypeProviders = PythonEngine.InteropConfiguration.PythonBaseTypeProviders; + baseTypeProviders.Add(new CustomBaseTypeProvider()); } } diff --git a/src/runtime/BaseTypeAttributeBase.cs b/src/runtime/BaseTypeAttributeBase.cs deleted file mode 100644 index c904cc5bb..000000000 --- a/src/runtime/BaseTypeAttributeBase.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace Python.Runtime -{ - /// - /// Base class for all attributes, that override base type for C# classes as seen from Python - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum - | AttributeTargets.Interface | AttributeTargets.Struct, - AllowMultiple = false, - Inherited = true)] - public class BaseTypeAttributeBase : Attribute - { - /// - /// Get a tuple of Python type(s), that should be presented to Python as the base type(s) - /// for the specified .NET type. - /// - public virtual PyTuple BaseTypes(Type type) { - if (type == null) throw new ArgumentNullException(nameof(type)); - if (type == typeof(Exception)) - { - return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(Exceptions.Exception))); - } - - if (type.BaseType != null) { - ClassBase bc = ClassManager.GetClass(type.BaseType); - return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(bc.pyHandle))); - } - - return PyTuple.FromSingleElement(new PyObject(new BorrowedReference(Runtime.PyBaseObjectType))); - } - - internal static BaseTypeAttributeBase Default { get; } = new BaseTypeAttributeBase(); - } -} diff --git a/src/runtime/CoreBaseTypeProvider.cs b/src/runtime/CoreBaseTypeProvider.cs new file mode 100644 index 000000000..0df6e877b --- /dev/null +++ b/src/runtime/CoreBaseTypeProvider.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace Python.Runtime +{ + /// + /// Minimal Python base type provider + /// + public sealed class CoreBaseTypeProvider : IPythonBaseTypeProvider + { + public IEnumerable GetBaseTypes(Type type, IList existingBases) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + if (existingBases is null) + throw new ArgumentNullException(nameof(existingBases)); + if (existingBases.Count > 0) + throw new ArgumentException("To avoid confusion, this type provider requires the initial set of base types to be empty"); + + return new[] { new PyObject(GetBaseType(type)) }; + } + + static BorrowedReference GetBaseType(Type type) + { + if (type == typeof(Exception)) + return new BorrowedReference(Exceptions.Exception); + + return type.BaseType != null + ? ClassManager.GetClass(type.BaseType).Instance + : new BorrowedReference(Runtime.PyBaseObjectType); + } + + CoreBaseTypeProvider(){} + public static CoreBaseTypeProvider Instance { get; } = new CoreBaseTypeProvider(); + } +} diff --git a/src/runtime/IPythonBaseTypeProvider.cs b/src/runtime/IPythonBaseTypeProvider.cs new file mode 100644 index 000000000..e7f641201 --- /dev/null +++ b/src/runtime/IPythonBaseTypeProvider.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace Python.Runtime +{ + public interface IPythonBaseTypeProvider + { + /// + /// Get Python types, that should be presented to Python as the base types + /// for the specified .NET type. + /// + IEnumerable GetBaseTypes(Type type, IList existingBases); + } +} diff --git a/src/runtime/InteropConfiguration.cs b/src/runtime/InteropConfiguration.cs new file mode 100644 index 000000000..7ca5f9d3a --- /dev/null +++ b/src/runtime/InteropConfiguration.cs @@ -0,0 +1,21 @@ +namespace Python.Runtime +{ + using System; + using System.Collections.Generic; + using Python.Runtime.Mixins; + + public sealed class InteropConfiguration + { + internal readonly PythonBaseTypeProviderGroup pythonBaseTypeProviders + = new PythonBaseTypeProviderGroup(); + public IList PythonBaseTypeProviders => this.pythonBaseTypeProviders; + + public static InteropConfiguration Default => new InteropConfiguration + { + PythonBaseTypeProviders = + { + CoreBaseTypeProvider.Instance, + }, + }; + } +} diff --git a/src/runtime/PythonBaseTypeProviderGroup.cs b/src/runtime/PythonBaseTypeProviderGroup.cs new file mode 100644 index 000000000..201960f89 --- /dev/null +++ b/src/runtime/PythonBaseTypeProviderGroup.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Python.Runtime +{ + class PythonBaseTypeProviderGroup : List, IPythonBaseTypeProvider + { + public IEnumerable GetBaseTypes(Type type, IList existingBases) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + if (existingBases is null) + throw new ArgumentNullException(nameof(existingBases)); + + foreach (var provider in this) + { + existingBases = provider.GetBaseTypes(type, existingBases).ToList(); + } + + return existingBases; + } + } +} diff --git a/src/runtime/Util.cs b/src/runtime/Util.cs index 5b7db8691..6b0b68243 100644 --- a/src/runtime/Util.cs +++ b/src/runtime/Util.cs @@ -34,38 +34,6 @@ internal static void WriteCLong(IntPtr type, int offset, Int64 flags) } } - /// - /// Walks the hierarchy of searching for the first - /// attribute of type from the down to . - /// - /// Type of the attribute to search for - /// The type potentially marked with the desired attribute - internal static T GetLatestAttribute(Type type) where T : Attribute - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - while (type != null) - { - var attribute = (T)type.GetCustomAttributes(attributeType: typeof(T), inherit: false).SingleOrDefault(); - if (attribute != null) - { - return attribute; - } - - if (type == typeof(object)) - { - return null; - } - - type = type.BaseType; - } - - return null; - } - /// /// Null-coalesce: if parameter is not /// , return it. Otherwise return . diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index ba304d632..20fb389ae 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -17,6 +17,7 @@ public class PythonEngine : IDisposable private static IntPtr _pythonHome = IntPtr.Zero; private static IntPtr _programName = IntPtr.Zero; private static IntPtr _pythonPath = IntPtr.Zero; + private static InteropConfiguration interopConfiguration = InteropConfiguration.Default; public PythonEngine() { @@ -56,6 +57,18 @@ internal static DelegateManager DelegateManager } } + public static InteropConfiguration InteropConfiguration + { + get => interopConfiguration; + set + { + if (IsInitialized) + throw new NotSupportedException("Changing interop configuration when engine is running is not supported"); + + interopConfiguration = value ?? throw new ArgumentNullException(nameof(InteropConfiguration)); + } + } + public static string ProgramName { get @@ -320,6 +333,8 @@ public static void Shutdown() PyObjectConversions.Reset(); initialized = false; + + InteropConfiguration = InteropConfiguration.Default; } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index dcfa3b681..ddc9886ce 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -17,6 +17,7 @@ internal static class TypeManager { private static BindingFlags tbFlags; private static Dictionary cache; + private static IPythonBaseTypeProvider pythonBaseTypeProvider; static TypeManager() { @@ -27,6 +28,7 @@ static TypeManager() public static void Reset() { cache = new Dictionary(128); + pythonBaseTypeProvider = PythonEngine.InteropConfiguration.pythonBaseTypeProviders; } /// @@ -275,27 +277,20 @@ static string CleanupFullName(string fullTypeName) static PyTuple GetBaseTypeTuple(Type clrType) { - if (clrType == typeof(Exception)) { - var exception = new PyObject(new BorrowedReference(Exceptions.Exception)); - return PyTuple.FromSingleElement(exception); - } - - var baseOverride = Util.GetLatestAttribute(clrType) - ?? BaseTypeAttributeBase.Default; - var types = baseOverride.BaseTypes(clrType); - if (types is null || types.Length() == 0) + var bases = pythonBaseTypeProvider + .GetBaseTypes(clrType, new PyObject[0]) + ?.ToArray(); + if (bases is null || bases.Length == 0) { throw new InvalidOperationException("At least one base type must be specified"); } - for (int index = 0; index < types.Length(); index++) { - IntPtr baseType = Runtime.PyTuple_GetItem(types.Handle, index); - if (!PyType.IsTypeType(baseType)) { - throw new InvalidOperationException("Entries in base types must be Python types themselves"); - } + if (bases.Any(@base => !PyType.IsTypeType(@base))) + { + throw new InvalidOperationException("Entries in base types must be Python types"); } - return types; + return new PyTuple(bases); } internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) From cb94e72f3e99cac1917266ca1fb9cdde5f02918f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 19:05:40 -0700 Subject: [PATCH 152/240] added a few mixins to reflected .NET collection types, that implement corresponding pythonic interfaces --- src/runtime/InteropConfiguration.cs | 1 + .../Mixins/CollectionMixinsProvider.cs | 78 +++++++++++++++++++ src/runtime/Mixins/collections.py | 61 +++++++++++++++ src/runtime/Python.Runtime.15.csproj | 4 +- src/runtime/Util.cs | 3 + src/runtime/importhook.cs | 1 + src/runtime/pyscope.cs | 2 +- src/runtime/pythonengine.cs | 44 +++++++++-- src/runtime/runtime.cs | 23 +++--- 9 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 src/runtime/Mixins/CollectionMixinsProvider.cs create mode 100644 src/runtime/Mixins/collections.py diff --git a/src/runtime/InteropConfiguration.cs b/src/runtime/InteropConfiguration.cs index 7ca5f9d3a..f3afa13a7 100644 --- a/src/runtime/InteropConfiguration.cs +++ b/src/runtime/InteropConfiguration.cs @@ -15,6 +15,7 @@ internal readonly PythonBaseTypeProviderGroup pythonBaseTypeProviders PythonBaseTypeProviders = { CoreBaseTypeProvider.Instance, + new CollectionMixinsProvider(new Lazy(() => Py.Import("clr._extras.collections"))), }, }; } diff --git a/src/runtime/Mixins/CollectionMixinsProvider.cs b/src/runtime/Mixins/CollectionMixinsProvider.cs new file mode 100644 index 000000000..3a5d4e283 --- /dev/null +++ b/src/runtime/Mixins/CollectionMixinsProvider.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Python.Runtime.Mixins +{ + class CollectionMixinsProvider: IPythonBaseTypeProvider + { + readonly Lazy mixinsModule; + public CollectionMixinsProvider(Lazy mixinsModule) + { + this.mixinsModule = mixinsModule ?? throw new ArgumentNullException(nameof(mixinsModule)); + } + + public PyObject Mixins => this.mixinsModule.Value; + + public IEnumerable GetBaseTypes(Type type, IList existingBases) + { + if (type is null) + throw new ArgumentNullException(nameof(type)); + + if (existingBases is null) + throw new ArgumentNullException(nameof(existingBases)); + + foreach (PyObject existingBase in existingBases) + yield return existingBase; + + var interfaces = NewInterfaces(type).Select(GetDefinition).ToArray(); + + // dictionaries + if (interfaces.Contains(typeof(IDictionary<,>))) + { + yield return this.Mixins.GetAttr("MutableMappingMixin"); +#if NETSTANDARD + } else if (interfaces.Contains(typeof(IReadOnlyDictionary<,>))) + { + yield return this.Mixins.GetAttr("MappingMixin"); +#endif + } + + // item collections + if (interfaces.Contains(typeof(IList<>)) + || interfaces.Contains(typeof(System.Collections.IList))) + { + yield return this.Mixins.GetAttr("MutableSequenceMixin"); +#if NETSTANDARD + } else if (interfaces.Contains(typeof(IReadOnlyList<>))) + { + yield return this.Mixins.GetAttr("SequenceMixin"); +#endif + } else if (interfaces.Contains(typeof(ICollection<>)) + || interfaces.Contains(typeof(System.Collections.ICollection))) + { + yield return this.Mixins.GetAttr("CollectionMixin"); + } else if (interfaces.Contains(typeof(System.Collections.IEnumerable))) + { + yield return this.Mixins.GetAttr("IterableMixin"); + } + + // enumerators + if (interfaces.Contains(typeof(System.Collections.IEnumerator))) + { + yield return this.Mixins.GetAttr("IteratorMixin"); + } + } + + static Type[] NewInterfaces(Type type) + { + var result = type.GetInterfaces(); + return type.BaseType != null + ? result.Except(type.BaseType.GetInterfaces()).ToArray() + : result; + } + + static Type GetDefinition(Type type) + => type.IsGenericType ? type.GetGenericTypeDefinition() : type; + } +} diff --git a/src/runtime/Mixins/collections.py b/src/runtime/Mixins/collections.py new file mode 100644 index 000000000..d38738295 --- /dev/null +++ b/src/runtime/Mixins/collections.py @@ -0,0 +1,61 @@ +""" +Implements collections.abc for common .NET types +https://docs.python.org/3.6/library/collections.abc.html +""" + +import collections.abc as col + +class IteratorMixin(col.Iterator): + def close(self): + self.Dispose() + +class IterableMixin(col.Iterable): + pass + +class SizedMixin(col.Sized): + def __len__(self): return self.Count + +class ContainerMixin(col.Container): + def __contains__(self, item): return self.Contains(item) + +try: + abc_Collection = col.Collection +except AttributeError: + # Python 3.5- does not have collections.abc.Collection + abc_Collection = col.Container + +class CollectionMixin(SizedMixin, IterableMixin, ContainerMixin, abc_Collection): + pass + +class SequenceMixin(CollectionMixin, col.Sequence): + pass + +class MutableSequenceMixin(SequenceMixin, col.MutableSequence): + pass + +class MappingMixin(CollectionMixin, col.Mapping): + def keys(self): return self.Keys + def items(self): return self + def values(self): return self.Values + def __iter__(self): raise NotImplementedError + def get(self, key): + _, item = self.TryGetValue(key) + return item + +class MutableMappingMixin(MappingMixin, col.MutableMapping): + def __delitem__(self, key): + return self.Remove(key) + def clear(self): + self.Clear() + def pop(self, key): + return self.Remove(key) + def setdefault(self, key, value): + existed, item = self.TryGetValue(key) + if existed: + return item + else: + self[key] = value + return value + def update(self, items): + for key, value in items: + self[key] = value diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 4d00136b8..499cbcf49 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -52,9 +52,6 @@ - - - @@ -64,6 +61,7 @@ clr.py + diff --git a/src/runtime/Util.cs b/src/runtime/Util.cs index 6b0b68243..7435b31fe 100644 --- a/src/runtime/Util.cs +++ b/src/runtime/Util.cs @@ -9,6 +9,9 @@ internal static class Util internal const string UnstableApiMessage = "This API is unstable, and might be changed or removed in the next minor release"; + internal const string UseOverloadWithReferenceTypes = + "This API is unsafe, and will be removed in the future. Use overloads working with *Reference types"; + internal static Int64 ReadCLong(IntPtr tp, int offset) { // On Windows, a C long is always 32 bits. diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index 6cec8f96c..b16c8d2c1 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -12,6 +12,7 @@ internal class ImportHook private static CLRModule root; private static MethodWrapper hook; private static IntPtr py_clr_module; + public static BorrowedReference ClrModule => new BorrowedReference(py_clr_module); private static IntPtr module_def = IntPtr.Zero; diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index 9a97b9695..eed13677e 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -70,7 +70,7 @@ internal PyScope(IntPtr ptr, PyScopeManager manager) Runtime.CheckExceptionOccurred(); Runtime.PyDict_SetItemString( - variables, "__builtins__", + VarsReference, "__builtins__", Runtime.PyEval_GetBuiltins() ); this.Name = this.Get("__name__"); diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 20fb389ae..70dff80dd 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -214,15 +214,13 @@ 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); + var clr_dict = Runtime.PyModule_GetDict(new BorrowedReference(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(); - Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); + var module = DefineModule("clr._extras"); + var module_globals = Runtime.PyModule_GetDict(module); Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream stream = assembly.GetManifestResourceStream("clr.py")) @@ -230,9 +228,11 @@ 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.DangerousGetAddress(), locals.Handle); } + LoadExtraModules(module_globals); + // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. Runtime.PyDict_SetItemString(clr_dict, "_extras", module); @@ -241,7 +241,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(); @@ -254,6 +254,34 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, } } + static BorrowedReference DefineModule(string name) + { + var module = Runtime.PyImport_AddModule(name); + var module_globals = Runtime.PyModule_GetDict(module); + var builtins = Runtime.PyEval_GetBuiltins(); + Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); + return module; + } + + static void LoadExtraModules(BorrowedReference targetModuleDict) + { + Assembly assembly = Assembly.GetExecutingAssembly(); + foreach (string nested in new[] {"collections"}) + { + var module = DefineModule("clr._extras." + nested); + var module_globals = Runtime.PyModule_GetDict(module); + string resourceName = typeof(PythonEngine).Namespace + ".Mixins." + nested + ".py"; + using (var stream = assembly.GetManifestResourceStream(resourceName)) + using (var reader = new StreamReader(stream)) + { + string pyCode = reader.ReadToEnd(); + Exec(pyCode, module_globals.DangerousGetAddress(), module_globals.DangerousGetAddress()); + } + + Runtime.PyDict_SetItemString(targetModuleDict, nested, module); + } + } + static void OnDomainUnload(object _, EventArgs __) { Shutdown(); @@ -585,7 +613,7 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, { globals = Runtime.PyDict_New(); Runtime.PyDict_SetItemString( - globals.Value, "__builtins__", + new BorrowedReference(globals.Value), "__builtins__", Runtime.PyEval_GetBuiltins() ); borrowedGlobals = false; diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index cba76577e..8e8854a56 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -798,7 +798,7 @@ public static int Py_Main( internal static void PyEval_RestoreThread(IntPtr tstate) => Delegates.PyEval_RestoreThread(tstate); - internal static IntPtr PyEval_GetBuiltins() => Delegates.PyEval_GetBuiltins(); + internal static BorrowedReference PyEval_GetBuiltins() => Delegates.PyEval_GetBuiltins(); internal static IntPtr PyEval_GetGlobals() => Delegates.PyEval_GetGlobals(); @@ -1477,12 +1477,14 @@ internal static bool PyDict_Check(IntPtr ob) internal static IntPtr PyDict_GetItemString(IntPtr pointer, string key) => Delegates.PyDict_GetItemString(pointer, key); - internal static int PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value) => Delegates.PyDict_SetItem(pointer, key, value); + internal static int PyDict_SetItem(BorrowedReference pointer, BorrowedReference key, BorrowedReference value) => Delegates.PyDict_SetItem(pointer, key, value); internal static int PyDict_SetItemString(IntPtr pointer, string key, IntPtr value) => Delegates.PyDict_SetItemString(pointer, key, value); + internal static int PyDict_SetItemString(BorrowedReference pointer, string key, BorrowedReference value) + => PyDict_SetItemString(pointer.DangerousGetAddress(), key, value.DangerousGetAddress()); + - internal static int PyDict_DelItem(IntPtr pointer, IntPtr key) => Delegates.PyDict_DelItem(pointer, key); @@ -1670,10 +1672,13 @@ internal static bool PyIter_Check(IntPtr pointer) internal static string PyModule_GetName(IntPtr module) => Delegates.PyModule_GetName(module); - + + [Obsolete(Util.UseOverloadWithReferenceTypes)] internal static IntPtr PyModule_GetDict(IntPtr module) => Delegates.PyModule_GetDict(module); + internal static BorrowedReference PyModule_GetDict(BorrowedReference module) + => new BorrowedReference(PyModule_GetDict(module.DangerousGetAddress())); + - internal static string PyModule_GetFilename(IntPtr module) => Delegates.PyModule_GetFilename(module); internal static IntPtr PyModule_Create2(IntPtr module, int apiver) => Delegates.PyModule_Create2(module, apiver); @@ -1684,7 +1689,7 @@ internal static bool PyIter_Check(IntPtr pointer) internal static IntPtr PyImport_ReloadModule(IntPtr module) => Delegates.PyImport_ReloadModule(module); - internal static IntPtr PyImport_AddModule(string name) => Delegates.PyImport_AddModule(name); + internal static BorrowedReference PyImport_AddModule(string name) => Delegates.PyImport_AddModule(name); internal static IntPtr PyImport_GetModuleDict() => Delegates.PyImport_GetModuleDict(); @@ -2232,7 +2237,7 @@ internal delegate int Py_MainDelegate( internal static PyEval_GetBuiltinsDelegate PyEval_GetBuiltins { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate IntPtr PyEval_GetBuiltinsDelegate(); + internal delegate BorrowedReference PyEval_GetBuiltinsDelegate(); internal static PyEval_GetGlobalsDelegate PyEval_GetGlobals { get; } @@ -2864,7 +2869,7 @@ IntPtr size internal static PyDict_SetItemDelegate PyDict_SetItem { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate int PyDict_SetItemDelegate(IntPtr pointer, IntPtr key, IntPtr value); + internal delegate int PyDict_SetItemDelegate(BorrowedReference pointer, BorrowedReference key, BorrowedReference value); internal static PyDict_SetItemStringDelegate PyDict_SetItemString { get; } @@ -3049,7 +3054,7 @@ IntPtr size internal static PyImport_AddModuleDelegate PyImport_AddModule { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate IntPtr PyImport_AddModuleDelegate(string name); + internal delegate BorrowedReference PyImport_AddModuleDelegate(string name); internal static PyImport_GetModuleDictDelegate PyImport_GetModuleDict { get; } From 9ce3a46a8bf9a556dbd183840404bbae4a6a5a48 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 23 May 2020 19:38:53 -0700 Subject: [PATCH 153/240] codec interfaces are now stable --- src/runtime/converterextensions.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index 2996d8499..a79241098 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -10,7 +10,6 @@ namespace Python.Runtime /// /// Defines conversion to CLR types (unmarshalling) /// - [Obsolete(Util.UnstableApiMessage)] public interface IPyObjectDecoder { /// @@ -30,7 +29,6 @@ public interface IPyObjectDecoder /// /// Defines conversion from CLR objects into Python objects (e.g. ) (marshalling) /// - [Obsolete(Util.UnstableApiMessage)] public interface IPyObjectEncoder { /// From a91993ac9930dd9fee856d61ec5fcec88a256e97 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 28 May 2020 17:20:54 -0700 Subject: [PATCH 154/240] refactored LoadExtraModules for Mixins into LoadSubmodule + LoadMixins --- src/runtime/Util.cs | 12 ++++++++++++ src/runtime/pythonengine.cs | 35 ++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/runtime/Util.cs b/src/runtime/Util.cs index 7435b31fe..d82f7693e 100644 --- a/src/runtime/Util.cs +++ b/src/runtime/Util.cs @@ -43,5 +43,17 @@ internal static void WriteCLong(IntPtr type, int offset, Int64 flags) /// internal static IntPtr Coalesce(this IntPtr primary, IntPtr fallback) => primary == IntPtr.Zero ? fallback : primary; + + /// + /// Gets substring after last occurrence of + /// + internal static string AfterLast(this string str, char symbol) + { + if (str is null) + throw new ArgumentNullException(nameof(str)); + + int last = str.LastIndexOf(symbol); + return last >= 0 ? str.Substring(last + 1) : null; + } } } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 70dff80dd..6ecca37e2 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -231,7 +232,7 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, Exec(clr_py, module_globals.DangerousGetAddress(), locals.Handle); } - LoadExtraModules(module_globals); + LoadMixins(module_globals); // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. @@ -263,23 +264,31 @@ static BorrowedReference DefineModule(string name) return module; } - static void LoadExtraModules(BorrowedReference targetModuleDict) + static void LoadMixins(BorrowedReference targetModuleDict) { - Assembly assembly = Assembly.GetExecutingAssembly(); foreach (string nested in new[] {"collections"}) { - var module = DefineModule("clr._extras." + nested); - var module_globals = Runtime.PyModule_GetDict(module); - string resourceName = typeof(PythonEngine).Namespace + ".Mixins." + nested + ".py"; - using (var stream = assembly.GetManifestResourceStream(resourceName)) - using (var reader = new StreamReader(stream)) - { - string pyCode = reader.ReadToEnd(); - Exec(pyCode, module_globals.DangerousGetAddress(), module_globals.DangerousGetAddress()); - } + LoadSubmodule(targetModuleDict, + fullName: "clr._extras." + nested, + resourceName: typeof(PythonEngine).Namespace + ".Mixins." + nested + ".py"); + } + } - Runtime.PyDict_SetItemString(targetModuleDict, nested, module); + static void LoadSubmodule(BorrowedReference targetModuleDict, string fullName, string resourceName) + { + string memberName = fullName.AfterLast('.'); + Debug.Assert(memberName != null); + Assembly assembly = Assembly.GetExecutingAssembly(); + var module = DefineModule(fullName); + var module_globals = Runtime.PyModule_GetDict(module); + using (var stream = assembly.GetManifestResourceStream(resourceName)) + using (var reader = new StreamReader(stream)) + { + string pyCode = reader.ReadToEnd(); + Exec(pyCode, module_globals.DangerousGetAddress(), module_globals.DangerousGetAddress()); } + + Runtime.PyDict_SetItemString(targetModuleDict, memberName, module); } static void OnDomainUnload(object _, EventArgs __) From e4aa4a437e79d1c931f98d4a7003ba649aedd96a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 28 May 2020 17:43:46 -0700 Subject: [PATCH 155/240] Runtime.InspectModule is internal --- src/runtime/runtime.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 8e8854a56..4c8e14b88 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -486,7 +486,7 @@ private static void ResetPyMembers() internal static IntPtr Error; private static Lazy inspect; - public static PyObject InspectModule => inspect.Value; + internal static PyObject InspectModule => inspect.Value; /// /// Check if any Python Exceptions occurred. From 9d3755716394e6090d7bb4d3a1c598eff6b0a7c5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 28 May 2020 18:42:47 -0700 Subject: [PATCH 156/240] enabled decoding instanceless exceptions Added new class clr.interop.PyErr with optional type, value, and traceback attributes. User can register decoders for it, that would let them decode instanceless (and even typeless) Python exceptions. These decoders will be invoked before the regular exception instance decoders. --- src/embed_tests/Codecs.cs | 33 ++++++++++++++- src/runtime/Python.Runtime.15.csproj | 3 ++ src/runtime/pythonengine.cs | 2 + src/runtime/pythonexception.cs | 61 ++++++++++++++++++---------- src/runtime/resources/interop.py | 10 +++++ src/runtime/runtime.cs | 11 +++-- 6 files changed, 94 insertions(+), 26 deletions(-) create mode 100644 src/runtime/resources/interop.py diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 615509f3c..518fc024d 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -113,13 +113,24 @@ public void ExceptionDecoded() { Assert.AreEqual(TestExceptionMessage, error.Message); } + [Test] + public void ExceptionDecodedNoInstance() { + PyObjectConversions.RegisterDecoder(new InstancelessExceptionDecoder()); + using var _ = Py.GIL(); + using var scope = Py.CreateScope(); + var error = Assert.Throws(() => PythonEngine.Exec( + $"[].__iter__().__next__()")); + Assert.AreEqual(TestExceptionMessage, error.Message); + } + class ValueErrorWrapper : Exception { public ValueErrorWrapper(string message) : base(message) { } } class ValueErrorCodec : IPyObjectEncoder, IPyObjectDecoder { public bool CanDecode(PyObject objectType, Type targetType) - => this.CanEncode(targetType) && objectType.Equals(PythonEngine.Eval("ValueError")); + => this.CanEncode(targetType) + && PythonReferenceComparer.Instance.Equals(objectType, PythonEngine.Eval("ValueError")); public bool CanEncode(Type type) => type == typeof(ValueErrorWrapper) || typeof(ValueErrorWrapper).IsSubclassOf(type); @@ -135,6 +146,26 @@ public PyObject TryEncode(object value) { return PythonEngine.Eval("ValueError").Invoke(error.Message.ToPython()); } } + + class InstancelessExceptionDecoder : IPyObjectDecoder + { + readonly PyObject PyErr = Py.Import("clr.interop").GetAttr("PyErr"); + + public bool CanDecode(PyObject objectType, Type targetType) + => PythonReferenceComparer.Instance.Equals(PyErr, objectType); + + public bool TryDecode(PyObject pyObj, out T value) + { + if (pyObj.HasAttr("value")) + { + value = default; + return false; + } + + value = (T)(object)new ValueErrorWrapper(TestExceptionMessage); + return true; + } + } } class FakeEncoder : IPyObjectEncoder diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 499cbcf49..3c616cd1d 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -61,6 +61,9 @@ clr.py + + interop.py + diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 6ecca37e2..c25e42fcd 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -234,6 +234,8 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, LoadMixins(module_globals); + LoadSubmodule(module_globals, "clr.interop", "interop.py"); + // add the imported module to the clr module, and copy the API functions // and decorators into the main clr module. Runtime.PyDict_SetItemString(clr_dict, "_extras", module); diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index cb1fd2edb..80f682c60 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -101,6 +101,10 @@ internal static Exception FromPyErrOrNull() /// to assist control flow checks. /// internal static Exception ThrowLastAsClrException() { + // prevent potential interop errors in this method + // from crashing process with undebuggable StackOverflowException + RuntimeHelpers.EnsureSufficientExecutionStack(); + IntPtr gs = PythonEngine.AcquireLock(); try { Runtime.PyErr_Fetch(out var pyTypeHandle, out var pyValueHandle, out var pyTracebackHandle); @@ -135,36 +139,49 @@ static Exception FromPyErr(BorrowedReference pyTypeHandle, BorrowedReference pyV return e; } - if (!pyTypeHandle.IsNull && !pyValueHandle.IsNull) + var errorDict = new PyDict(); + if (!pyTypeHandle.IsNull) errorDict["type"] = new PyObject(pyTypeHandle); + if (!pyValueHandle.IsNull) errorDict["value"] = new PyObject(pyValueHandle); + if (!pyTracebackHandle.IsNull) errorDict["traceback"] = new PyObject(pyTracebackHandle); + + var pyErrType = Runtime.InteropModule.GetAttr("PyErr"); + var pyErrInfo = pyErrType.Invoke(new PyTuple(), errorDict); + if (PyObjectConversions.TryDecode(pyErrInfo.Reference, pyErrType.Reference, + typeof(Exception), out object decoded) && decoded is Exception decodedPyErrInfo) + { + return decodedPyErrInfo; + } + + if (!pyTypeHandle.IsNull) { - if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), - out object decoded) && decoded is Exception decodedException) { - return decodedException; + if (!pyValueHandle.IsNull) + { + if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), + out decoded) && decoded is Exception decodedException) { + return decodedException; + } + + using (var pyValue = new PyObject(pyValueHandle)) + { + msg = pyValue.ToString(); + var cause = pyValue.GetAttr("__cause__", null); + if (cause != null && cause.Handle != Runtime.PyNone) { + using var innerTraceback = cause.GetAttr("__traceback__", null); + inner = FromPyErr( + pyTypeHandle: cause.GetPythonTypeHandle(), + pyValueHandle: cause.Reference, + pyTracebackHandle: innerTraceback is null ? new BorrowedReference() : innerTraceback.Reference); + } + } } - string type; - string message; using (var pyType = new PyObject(pyTypeHandle)) using (PyObject pyTypeName = pyType.GetAttr("__name__")) { - type = pyTypeName.ToString(); + pythonTypeName = pyTypeName.ToString(); } - pythonTypeName = type; - - using (var pyValue = new PyObject(pyValueHandle)) - { - message = pyValue.ToString(); - var cause = pyValue.GetAttr("__cause__", null); - if (cause != null && cause.Handle != Runtime.PyNone) { - using var innerTraceback = cause.GetAttr("__traceback__", null); - inner = FromPyErr( - pyTypeHandle: cause.GetPythonTypeHandle(), - pyValueHandle: cause.Reference, - pyTracebackHandle: innerTraceback is null ? new BorrowedReference() : innerTraceback.Reference); - } - } - msg = type + " : " + message; + msg = string.IsNullOrEmpty(msg) ? pythonTypeName : pythonTypeName + " : " + msg; } if (!pyTracebackHandle.IsNull) { diff --git a/src/runtime/resources/interop.py b/src/runtime/resources/interop.py new file mode 100644 index 000000000..a47d16c68 --- /dev/null +++ b/src/runtime/resources/interop.py @@ -0,0 +1,10 @@ +_UNSET = object() + +class PyErr: + def __init__(self, type=_UNSET, value=_UNSET, traceback=_UNSET): + if not(type is _UNSET): + self.type = type + if not(value is _UNSET): + self.value = value + if not(traceback is _UNSET): + self.traceback = traceback diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 4c8e14b88..ab7bbd082 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -354,7 +354,8 @@ internal static void Initialize(bool initSigs = false) XDecref(item); AssemblyManager.UpdatePath(); - inspect = GetInspectModuleLazy(); + inspect = GetModuleLazy("inspect"); + clrInterop = GetModuleLazy("clr.interop"); } /// @@ -416,8 +417,10 @@ internal static void Shutdown() Py_Finalize(); } - private static Lazy GetInspectModuleLazy() - => new Lazy(() => PythonEngine.ImportModule("inspect"), isThreadSafe: false); + private static Lazy GetModuleLazy(string moduleName) + => moduleName is null + ? throw new ArgumentNullException(nameof(moduleName)) + : new Lazy(() => PythonEngine.ImportModule(moduleName), isThreadSafe: false); // called *without* the GIL acquired by clr._AtExit internal static int AtExit() @@ -487,6 +490,8 @@ private static void ResetPyMembers() private static Lazy inspect; internal static PyObject InspectModule => inspect.Value; + private static Lazy clrInterop; + internal static PyObject InteropModule => clrInterop.Value; /// /// Check if any Python Exceptions occurred. From 883d04ddae66a8b1c3143c1a5b48e928017023e3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 29 May 2020 22:08:15 -0700 Subject: [PATCH 157/240] fixed PyObject.As returning PyObject --- src/runtime/pyobject.cs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index dacb22054..52faa03bd 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -148,20 +148,7 @@ public object AsManagedObject(Type t) /// Return a managed object of the given type, based on the /// value of the Python object. /// - public T As() - { - if (typeof(T) == typeof(PyObject) || typeof(T) == typeof(object)) - { - return (T)(this as object); - } - object result; - if (!Converter.ToManaged(obj, typeof(T), out result, false)) - { - throw new InvalidCastException("cannot convert object to target type", - innerException: PythonException.FromPyErrOrNull()); - } - return (T)result; - } + public T As() => (T)this.AsManagedObject(typeof(T)); /// From f8381e1d6e79b12e0521150a0d9234075d7523fe Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 30 May 2020 01:11:35 -0700 Subject: [PATCH 158/240] fixed decoding of autogenerated AttributeError --- src/embed_tests/Codecs.cs | 28 ++++++++++++++++++++++++++++ src/runtime/pythonexception.cs | 12 ++++++++++-- src/runtime/runtime.cs | 3 +++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 518fc024d..6a0ce6bcd 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -123,6 +123,15 @@ public void ExceptionDecodedNoInstance() { Assert.AreEqual(TestExceptionMessage, error.Message); } + [Test] + public void ExceptionStringValue() { + PyObjectConversions.RegisterDecoder(new AttributeErrorDecoder()); + using var _ = Py.GIL(); + using var scope = Py.CreateScope(); + var error = Assert.Throws(() => "hi".ToPython().GetAttr("blah")); + StringAssert.Contains("blah", error.Message); + } + class ValueErrorWrapper : Exception { public ValueErrorWrapper(string message) : base(message) { } } @@ -147,6 +156,25 @@ public PyObject TryEncode(object value) { } } + class AttributeErrorWrapper : Exception { + public AttributeErrorWrapper(string message) : base(message) { } + } + + class AttributeErrorDecoder : IPyObjectDecoder { + public bool CanDecode(PyObject objectType, Type targetType) + => this.SupportsTargetType(targetType) + && PythonReferenceComparer.Instance.Equals(objectType, PythonEngine.Eval("AttributeError")); + + bool SupportsTargetType(Type type) => type == typeof(AttributeErrorWrapper) + || typeof(AttributeErrorWrapper).IsSubclassOf(type); + + public bool TryDecode(PyObject pyObj, out T value) { + var message = pyObj.GetAttr("args")[0].As(); + value = (T)(object)new AttributeErrorWrapper(message); + return true; + } + } + class InstancelessExceptionDecoder : IPyObjectDecoder { readonly PyObject PyErr = Py.Import("clr.interop").GetAttr("PyErr"); diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 80f682c60..0db435d5d 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -156,8 +156,16 @@ static Exception FromPyErr(BorrowedReference pyTypeHandle, BorrowedReference pyV { if (!pyValueHandle.IsNull) { - if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), - out decoded) && decoded is Exception decodedException) { + if (Runtime.PyString_Check(pyValueHandle) && pyTypeHandle != Runtime.PyStringType) { + using var type = new PyObject(pyTypeHandle); + using var message = new PyObject(pyValueHandle); + var instance = type.Invoke(message); + if (PyObjectConversions.TryDecode(instance.Reference, pyTypeHandle, typeof(Exception), + out decoded) && decoded is Exception decodedExceptionInstance) { + return decodedExceptionInstance; + } + } else if (PyObjectConversions.TryDecode(pyValueHandle, pyTypeHandle, typeof(Exception), + out decoded) && decoded is Exception decodedException) { return decodedException; } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index ab7bbd082..18ea20f59 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1341,10 +1341,13 @@ internal static bool IsStringType(IntPtr op) return (t == PyStringType) || (t == PyUnicodeType); } + [Obsolete(Util.UseOverloadWithReferenceTypes)] internal static bool PyString_Check(IntPtr ob) { return PyObject_TYPE(ob) == PyStringType; } + internal static bool PyString_Check(BorrowedReference ob) + => PyObject_TYPE(ob) == PyStringType; internal static IntPtr PyString_FromString(string value) { From 1c2e65140e90e8658bae99c261f8e71124cd489f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 30 May 2020 12:11:27 -0700 Subject: [PATCH 159/240] do not dispose items returned by PyIter after advancing to the next step --- src/embed_tests/TestRuntime.cs | 6 +++--- src/runtime/converter.cs | 26 ++++++++++++++------------ src/runtime/exceptions.cs | 2 ++ src/runtime/pyiter.cs | 34 +++++++--------------------------- src/runtime/pyobject.cs | 13 +++++-------- src/runtime/runtime.cs | 16 ++++++++-------- 6 files changed, 39 insertions(+), 58 deletions(-) diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs index 157fe4cb7..4ec3e8dcd 100644 --- a/src/embed_tests/TestRuntime.cs +++ b/src/embed_tests/TestRuntime.cs @@ -86,7 +86,7 @@ public static void PyCheck_Iter_PyObject_IsIterable_Test() Runtime.Runtime.Py_Initialize(); // Tests that a python list is an iterable, but not an iterator - var pyList = Runtime.Runtime.PyList_New(0); + var pyList = NewReference.DangerousFromPointer(Runtime.Runtime.PyList_New(0)); Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyList)); Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyList)); @@ -96,7 +96,7 @@ public static void PyCheck_Iter_PyObject_IsIterable_Test() Assert.IsTrue(Runtime.Runtime.PyIter_Check(pyListIter)); // Tests that a python float is neither an iterable nor an iterator - var pyFloat = Runtime.Runtime.PyFloat_FromDouble(2.73); + var pyFloat = NewReference.DangerousFromPointer(Runtime.Runtime.PyFloat_FromDouble(2.73)); Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(pyFloat)); Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyFloat)); @@ -118,7 +118,7 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test() if (lockType == IntPtr.Zero) throw new KeyNotFoundException("class 'Lock' was not found in 'threading'"); - var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0)); + var lockInstance = NewReference.DangerousFromPointer(Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0))); Exceptions.ErrorCheck(lockInstance); Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance)); diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index c9ad079ff..4bb7a74fb 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -777,9 +777,9 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s bool IsSeqObj = Runtime.PySequence_Check(value); var len = IsSeqObj ? Runtime.PySequence_Size(value) : -1; - IntPtr IterObject = Runtime.PyObject_GetIter(value); + var IterObject = Runtime.PyObject_GetIter(new BorrowedReference(value)); - if(IterObject==IntPtr.Zero) { + if(IterObject.IsNull()) { if (setError) { SetConversionError(value, obType); @@ -793,22 +793,24 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s var constructedListType = listType.MakeGenericType(elementType); IList list = IsSeqObj ? (IList) Activator.CreateInstance(constructedListType, new Object[] {(int) len}) : (IList) Activator.CreateInstance(constructedListType); - IntPtr item; + NewReference item; - while ((item = Runtime.PyIter_Next(IterObject)) != IntPtr.Zero) + while (!(item = Runtime.PyIter_Next(IterObject)).IsNull()) { - object obj = null; + try + { + if (!ToManaged(item.DangerousGetAddress(), elementType, out object obj, true)) + { + return false; + } - if (!Converter.ToManaged(item, elementType, out obj, true)) + list.Add(obj); + } finally { - Runtime.XDecref(item); - return false; + item.Dispose(); } - - list.Add(obj); - Runtime.XDecref(item); } - Runtime.XDecref(IterObject); + IterObject.Dispose(); items = Array.CreateInstance(elementType, list.Count); list.CopyTo(items, 0); diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 6bcca6843..816633385 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -200,6 +200,8 @@ internal static IntPtr ErrorCheck(IntPtr pointer) return pointer; } + internal static BorrowedReference ErrorCheck(BorrowedReference reference) + => reference.IsNull ? throw PythonException.ThrowLastAsClrException() : reference; /// /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index c993e4895..368ac57df 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -24,51 +24,31 @@ public class PyIter : PyObject, IEnumerator public PyIter(IntPtr ptr) : base(ptr) { } - - /// - /// PyIter Constructor - /// - /// - /// Creates a Python iterator from an iterable. Like doing "iter(iterable)" in python. - /// - public PyIter(PyObject iterable) - { - obj = Runtime.PyObject_GetIter(iterable.obj); - Exceptions.ErrorCheck(obj); - } + internal PyIter(BorrowedReference reference) : base(reference) { } protected override void Dispose(bool disposing) { - if (null != _current) - { - _current.Dispose(); - _current = null; - } + _current = null; base.Dispose(disposing); } public bool MoveNext() { - // dispose of the previous object, if there was one - if (null != _current) + var next = Runtime.PyIter_Next(Reference); + if (next.IsNull()) { - _current.Dispose(); + // dispose of the previous object, if there was one _current = null; - } - - IntPtr next = Runtime.PyIter_Next(obj); - if (next == IntPtr.Zero) - { return false; } - _current = new PyObject(next); + _current = next.MoveToPyObject(); return true; } public void Reset() { - //Not supported in python. + throw new NotSupportedException(); } public object Current diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 52faa03bd..73d93e28a 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -697,12 +697,12 @@ public virtual PyObject this[int index] /// to the Python expression "iter(object)". A PythonException will be /// raised if the object cannot be iterated. /// - public PyObject GetIterator() + public PyIter GetIterator() { DebugUtil.EnsureGIL(); - IntPtr r = Runtime.PyObject_GetIter(obj); + using var r = Runtime.PyObject_GetIter(Reference); Exceptions.ErrorCheck(r); - return new PyObject(r); + return new PyIter(r); } /// @@ -713,10 +713,7 @@ public PyObject GetIterator() /// python object to be iterated over in C#. A PythonException will be /// raised if the object is not iterable. /// - public IEnumerator GetEnumerator() - { - return new PyIter(this); - } + public IEnumerator GetEnumerator() => this.GetIterator(); /// @@ -989,7 +986,7 @@ public bool IsCallable() public bool IsIterable() { DebugUtil.EnsureGIL(); - return Runtime.PyObject_IsIterable(obj); + return Runtime.PyObject_IsIterable(Reference); } diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 18ea20f59..2f7fc9f7f 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -941,9 +941,9 @@ internal static string PyObject_GetTypeName(IntPtr op) /// /// Test whether the Python object is an iterable. /// - internal static bool PyObject_IsIterable(IntPtr pointer) + internal static bool PyObject_IsIterable(BorrowedReference pointer) { - var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); + var ob_type = Marshal.ReadIntPtr(pointer.DangerousGetAddress(), ObjectOffset.ob_type); IntPtr tp_iter = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iter); return tp_iter != IntPtr.Zero; } @@ -976,7 +976,7 @@ internal static bool PyObject_IsIterable(IntPtr pointer) 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 NewReference PyObject_GetIter(BorrowedReference op) => Delegates.PyObject_GetIter(op); internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw); @@ -1659,15 +1659,15 @@ internal static long PyTuple_Size(IntPtr pointer) // Python iterator API //==================================================================== - internal static bool PyIter_Check(IntPtr pointer) + internal static bool PyIter_Check(BorrowedReference pointer) { - var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); + var ob_type = Marshal.ReadIntPtr(pointer.DangerousGetAddress(), ObjectOffset.ob_type); IntPtr tp_iternext = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iternext); return tp_iternext != IntPtr.Zero && tp_iternext != _PyObject_NextNotImplemented; } - internal static IntPtr PyIter_Next(IntPtr pointer) => Delegates.PyIter_Next(pointer); + internal static NewReference PyIter_Next(BorrowedReference pointer) => Delegates.PyIter_Next(pointer); //==================================================================== @@ -2400,7 +2400,7 @@ internal delegate int Py_MainDelegate( internal static PyObject_GetIterDelegate PyObject_GetIter { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate IntPtr PyObject_GetIterDelegate(IntPtr op); + internal delegate NewReference PyObject_GetIterDelegate(BorrowedReference op); internal static PyObject_CallDelegate PyObject_Call { get; } @@ -3017,7 +3017,7 @@ IntPtr size internal static PyIter_NextDelegate PyIter_Next { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate IntPtr PyIter_NextDelegate(IntPtr pointer); + internal delegate NewReference PyIter_NextDelegate(BorrowedReference pointer); internal static PyModule_NewDelegate PyModule_New { get; } From 07525925ae7e909b5397bf5cf9c2b97b5381b177 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 30 May 2020 12:13:47 -0700 Subject: [PATCH 160/240] updated test frameworks --- src/embed_tests/Python.EmbeddingTest.15.csproj | 2 +- src/perf_tests/Python.PerformanceTests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj index 3c4249cbf..9ad1b5594 100644 --- a/src/embed_tests/Python.EmbeddingTest.15.csproj +++ b/src/embed_tests/Python.EmbeddingTest.15.csproj @@ -77,7 +77,7 @@ - + diff --git a/src/perf_tests/Python.PerformanceTests.csproj b/src/perf_tests/Python.PerformanceTests.csproj index 25af89db0..01328c4f9 100644 --- a/src/perf_tests/Python.PerformanceTests.csproj +++ b/src/perf_tests/Python.PerformanceTests.csproj @@ -21,7 +21,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + compile From cd78afec957256656c4da7c8261c5b1eec3f3af1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 13:45:52 -0700 Subject: [PATCH 161/240] replaced crash in tuple decoder on large tuples with refusal to decode --- src/runtime/Codecs/TupleCodecs.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs index a9ae33fe0..6c5c816a8 100644 --- a/src/runtime/Codecs/TupleCodecs.cs +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -74,6 +74,11 @@ public bool TryDecode(PyObject pyObj, out T value) value = (T)EmptyTuple; return true; } + if (itemCount >= tupleCreate.Length) + { + value = default; + return false; + } var elements = new object[itemCount]; for (int itemIndex = 0; itemIndex < itemTypes.Length; itemIndex++) @@ -98,6 +103,11 @@ static bool Decode(PyObject tuple, out object value) value = EmptyTuple; return true; } + if (itemCount >= tupleCreate.Length) + { + value = default; + return false; + } var elements = new object[itemCount]; var itemTypes = new Type[itemCount]; value = null; From f87dab715afa9ad834fccda49734e47d907d4c14 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 13:47:44 -0700 Subject: [PATCH 162/240] unwrap decoder exceptions --- src/runtime/converterextensions.cs | 18 ++++++++++++++++-- src/runtime/polyfill/ExceptionPolifills.cs | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/runtime/polyfill/ExceptionPolifills.cs diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index a79241098..59b310f98 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -117,7 +117,13 @@ internal static bool TryDecode(BorrowedReference obj, BorrowedReference objType, var decoder = pythonToClr.GetOrAdd(new TypePair(objType.DangerousGetAddress(), targetType), pair => GetDecoder(pair.PyType, pair.ClrType)); result = null; if (decoder == null) return false; - return decoder.Invoke(obj, out result); + try + { + return decoder.Invoke(obj, out result); + } catch (TargetInvocationException invocationException) + { + throw invocationException.InnerException.Rethrow(); + } } static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type targetType) @@ -136,7 +142,15 @@ bool TryDecode(BorrowedReference pyHandle, out object result) { var pyObj = new PyObject(pyHandle); var @params = new object[] { pyObj, null }; - bool success = (bool)decode.Invoke(decoder, @params); + bool success = false; + try + { + success = (bool)decode.Invoke(decoder, @params); + } catch (TargetInvocationException invocationException) + { + throw invocationException.InnerException.Rethrow(); + } + if (!success) { pyObj.Dispose(); diff --git a/src/runtime/polyfill/ExceptionPolifills.cs b/src/runtime/polyfill/ExceptionPolifills.cs new file mode 100644 index 000000000..923ff41a3 --- /dev/null +++ b/src/runtime/polyfill/ExceptionPolifills.cs @@ -0,0 +1,19 @@ +namespace Python.Runtime +{ + using System; + using System.Runtime.ExceptionServices; + + static class ExceptionPolifills + { + public static Exception Rethrow(this Exception exception) + { + if (exception is null) + throw new ArgumentNullException(nameof(exception)); + +#if NETSTANDARD + ExceptionDispatchInfo.Capture(exception).Throw(); +#endif + throw exception; + } + } +} From 1af70812ff306ac56977bd87e98d3d5a86f096f2 Mon Sep 17 00:00:00 2001 From: SnGmng <38666407+SnGmng@users.noreply.github.com> Date: Sun, 27 Oct 2019 20:35:42 +0100 Subject: [PATCH 163/240] Add Python buffer api support --- AUTHORS.md | 1 + CHANGELOG.md | 1 + src/embed_tests/Python.EmbeddingTest.csproj | 1 + src/embed_tests/TestPyBuffer.cs | 73 +++++++ src/runtime/Python.Runtime.csproj | 4 +- src/runtime/bufferinterface.cs | 116 ++++++++++ src/runtime/interop.cs | 2 +- src/runtime/pybuffer.cs | 227 ++++++++++++++++++++ src/runtime/pyobject.cs | 15 ++ src/runtime/runtime.cs | 95 ++++++++ 10 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 src/embed_tests/TestPyBuffer.cs create mode 100644 src/runtime/bufferinterface.cs create mode 100644 src/runtime/pybuffer.cs diff --git a/AUTHORS.md b/AUTHORS.md index b0d1f0c91..a8dabaed9 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -68,6 +68,7 @@ - ([@OneBlue](https://github.com/OneBlue)) - ([@rico-chet](https://github.com/rico-chet)) - ([@rmadsen-ks](https://github.com/rmadsen-ks)) +- ([@SnGmng](https://github.com/SnGmng)) - ([@stonebig](https://github.com/stonebig)) - ([@testrunner123](https://github.com/testrunner123)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 956e59135..7f121f431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Added support for __len__ for .NET classes that implement ICollection - Added `object.GetRawPythonProxy() -> PyObject` extension method, that bypasses any conversions - Added PythonException.Format method to format exceptions the same as traceback.format_exception +- Added Python 3 buffer api support and PyBuffer interface for fast byte and numpy array read/write ([#980][p980]) ### Changed diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 5dee66e64..94c8dca00 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -97,6 +97,7 @@ + diff --git a/src/embed_tests/TestPyBuffer.cs b/src/embed_tests/TestPyBuffer.cs new file mode 100644 index 000000000..8ad3fb6f9 --- /dev/null +++ b/src/embed_tests/TestPyBuffer.cs @@ -0,0 +1,73 @@ +using System; +using System.Text; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest { + public class TestPyBuffer + { + [SetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [TearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestBufferWrite() + { + if (Runtime.Runtime.PythonVersion < new Version(3,5)) return; + + string bufferTestString = "hello world! !$%&/()=?"; + + using (Py.GIL()) + { + using (var scope = Py.CreateScope()) + { + scope.Exec($"arr = bytearray({bufferTestString.Length})"); + PyObject pythonArray = scope.Get("arr"); + byte[] managedArray = new UTF8Encoding().GetBytes(bufferTestString); + + using (PyBuffer buf = pythonArray.GetBuffer()) + { + buf.Write(managedArray, 0, managedArray.Length); + } + + string result = scope.Eval("arr.decode('utf-8')").ToString(); + Assert.IsTrue(result == bufferTestString); + } + } + } + + [Test] + public void TestBufferRead() + { + if (Runtime.Runtime.PythonVersion < new Version(3, 5)) return; + + string bufferTestString = "hello world! !$%&/()=?"; + + using (Py.GIL()) + { + using (var scope = Py.CreateScope()) + { + scope.Exec($"arr = b'{bufferTestString}'"); + PyObject pythonArray = scope.Get("arr"); + byte[] managedArray = new byte[bufferTestString.Length]; + + using (PyBuffer buf = pythonArray.GetBuffer()) + { + buf.Read(managedArray, 0, managedArray.Length); + } + + string result = new UTF8Encoding().GetString(managedArray); + Assert.IsTrue(result == bufferTestString); + } + } + } + } +} diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 0a4359796..c3daa178d 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -88,6 +88,7 @@ + @@ -129,6 +130,7 @@ + @@ -180,4 +182,4 @@ - \ No newline at end of file + diff --git a/src/runtime/bufferinterface.cs b/src/runtime/bufferinterface.cs new file mode 100644 index 000000000..fe6cb6746 --- /dev/null +++ b/src/runtime/bufferinterface.cs @@ -0,0 +1,116 @@ +using System; +using System.Runtime.InteropServices; + +namespace Python.Runtime +{ + /* buffer interface */ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal struct Py_buffer { + public IntPtr buf; + public IntPtr obj; /* owned reference */ + [MarshalAs(UnmanagedType.SysInt)] + public IntPtr len; + [MarshalAs(UnmanagedType.SysInt)] + public IntPtr itemsize; /* This is Py_ssize_t so it can be + pointed to by strides in simple case.*/ + [MarshalAs(UnmanagedType.Bool)] + public bool _readonly; + public int ndim; + [MarshalAs(UnmanagedType.LPStr)] + public string format; + public IntPtr shape; + public IntPtr strides; + public IntPtr suboffsets; + public IntPtr _internal; + } + + public enum BufferOrderStyle: byte + { + C = (byte)'C', + Fortran = (byte)'F', + EitherOne = (byte)'A', + } + + /* Flags for getting buffers */ + [Flags] + public enum PyBUF: int + { + /// + /// Simple buffer without shape strides and suboffsets + /// + SIMPLE = 0, + /// + /// Controls the field. If set, the exporter MUST provide a writable buffer or else report failure. Otherwise, the exporter MAY provide either a read-only or writable buffer, but the choice MUST be consistent for all consumers. + /// + WRITABLE = 0x0001, + /// + /// Controls the field. If set, this field MUST be filled in correctly. Otherwise, this field MUST be NULL. + /// + FORMATS = 0x0004, + /// + /// N-Dimensional buffer with shape + /// + ND = 0x0008, + /// + /// Buffer with strides and shape + /// + STRIDES = (0x0010 | ND), + /// + /// C-Contigous buffer with strides and shape + /// + C_CONTIGUOUS = (0x0020 | STRIDES), + /// + /// F-Contigous buffer with strides and shape + /// + F_CONTIGUOUS = (0x0040 | STRIDES), + /// + /// C or Fortran contigous buffer with strides and shape + /// + ANY_CONTIGUOUS = (0x0080 | STRIDES), + /// + /// Buffer with suboffsets (if needed) + /// + INDIRECT = (0x0100 | STRIDES), + /// + /// Writable C-Contigous buffer with shape + /// + CONTIG = (ND | WRITABLE), + /// + /// Readonly C-Contigous buffer with shape + /// + CONTIG_RO = (ND), + /// + /// Writable buffer with shape and strides + /// + STRIDED = (STRIDES | WRITABLE), + /// + /// Readonly buffer with shape and strides + /// + STRIDED_RO = (STRIDES), + /// + /// Writable buffer with shape, strides and format + /// + RECORDS = (STRIDES | WRITABLE | FORMATS), + /// + /// Readonly buffer with shape, strides and format + /// + RECORDS_RO = (STRIDES | FORMATS), + /// + /// Writable indirect buffer with shape, strides, format and suboffsets (if needed) + /// + FULL = (INDIRECT | WRITABLE | FORMATS), + /// + /// Readonly indirect buffer with shape, strides, format and suboffsets (if needed) + /// + FULL_RO = (INDIRECT | FORMATS), + } + + internal struct PyBufferProcs + { + public IntPtr Get; + public IntPtr Release; + } + + delegate int GetBufferProc(BorrowedReference obj, out Py_buffer buffer, PyBUF flags); + delegate void ReleaseBufferProc(BorrowedReference obj, ref Py_buffer buffer); +} diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index aed7a0ce5..67a49dffd 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -97,7 +97,7 @@ public static int InstanceGCHandle(BorrowedReference type) #if DEBUG Debug.Assert(ManagedType.IsManagedType(type)); var meta = Runtime.PyObject_TYPE(type); - if (meta.DangerousGetAddress() != Runtime.PyCLRMetaType) + if (Runtime.PyCLRMetaType != IntPtr.Zero && meta.DangerousGetAddress() != Runtime.PyCLRMetaType) Debug.Assert(new PyObject(meta).ToString() == ""); #endif int offset = (int)Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.clr_gchandle_offset); diff --git a/src/runtime/pybuffer.cs b/src/runtime/pybuffer.cs new file mode 100644 index 000000000..bcd7ed64e --- /dev/null +++ b/src/runtime/pybuffer.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Python.Runtime +{ + public sealed class PyBuffer : IDisposable + { + private PyObject _exporter; + private Py_buffer _view; + + unsafe internal PyBuffer(PyObject exporter, PyBUF flags) + { + if (Runtime.PyObject_GetBuffer(exporter.Reference, out _view, flags) < 0) + { + throw PythonException.ThrowLastAsClrException(); + } + + _exporter = exporter; + + var intPtrBuf = new IntPtr[_view.ndim]; + if (_view.shape != IntPtr.Zero) + { + Marshal.Copy(_view.shape, intPtrBuf, 0, (int)_view.len * sizeof(IntPtr)); + Shape = intPtrBuf.Select(x => (long)x).ToArray(); + } + + if (_view.strides != IntPtr.Zero) { + Marshal.Copy(_view.strides, intPtrBuf, 0, (int)_view.len * sizeof(IntPtr)); + Strides = intPtrBuf.Select(x => (long)x).ToArray(); + } + + if (_view.suboffsets != IntPtr.Zero) { + Marshal.Copy(_view.suboffsets, intPtrBuf, 0, (int)_view.len * sizeof(IntPtr)); + SubOffsets = intPtrBuf.Select(x => (long)x).ToArray(); + } + } + + public PyObject Object => _exporter; + public long Length => (long)_view.len; + public long ItemSize => (long)_view.itemsize; + public int Dimensions => _view.ndim; + public bool ReadOnly => _view._readonly; + public IntPtr Buffer => _view.buf; + public string Format => _view.format; + + /// + /// An array of length indicating the shape of the memory as an n-dimensional array. + /// + public long[] Shape { get; private set; } + + /// + /// An array of length giving the number of bytes to skip to get to a new element in each dimension. + /// Will be null except when PyBUF_STRIDES or PyBUF_INDIRECT flags in GetBuffer/>. + /// + public long[] Strides { get; private set; } + + /// + /// An array of Py_ssize_t of length ndim. If suboffsets[n] >= 0, + /// the values stored along the nth dimension are pointers and the suboffset value dictates how many bytes to add to each pointer after de-referencing. + /// A suboffset value that is negative indicates that no de-referencing should occur (striding in a contiguous memory block). + /// + public long[] SubOffsets { get; private set; } + + /// + /// Return the implied itemsize from format. On error, raise an exception and return -1. + /// New in version 3.9. + /// + public static long SizeFromFormat(string format) + { + if (Runtime.PythonVersion < new Version(3, 9)) + throw new NotSupportedException("SizeFromFormat requires at least Python 3.9"); + return (long)Runtime.PyBuffer_SizeFromFormat(format); + } + + /// + /// Returns true if the memory defined by the view is C-style (order is 'C') or Fortran-style (order is 'F') contiguous or either one (order is 'A'). Returns false otherwise. + /// + /// C-style (order is 'C') or Fortran-style (order is 'F') contiguous or either one (order is 'A') + public bool IsContiguous(BufferOrderStyle order) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + return Convert.ToBoolean(Runtime.PyBuffer_IsContiguous(ref _view, order)); + } + + /// + /// Get the memory area pointed to by the indices inside the given view. indices must point to an array of view->ndim indices. + /// + public IntPtr GetPointer(long[] indices) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (Runtime.PythonVersion < new Version(3, 7)) + throw new NotSupportedException("GetPointer requires at least Python 3.7"); + return Runtime.PyBuffer_GetPointer(ref _view, indices.Select(x => (IntPtr)x).ToArray()); + } + + /// + /// Copy contiguous len bytes from buf to view. fort can be 'C' or 'F' (for C-style or Fortran-style ordering). + /// + public void FromContiguous(IntPtr buf, long len, BufferOrderStyle fort) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (Runtime.PythonVersion < new Version(3, 7)) + throw new NotSupportedException("FromContiguous requires at least Python 3.7"); + + if (Runtime.PyBuffer_FromContiguous(ref _view, buf, (IntPtr)len, fort) < 0) + throw PythonException.ThrowLastAsClrException(); + } + + /// + /// Copy len bytes from view to its contiguous representation in buf. order can be 'C' or 'F' or 'A' (for C-style or Fortran-style ordering or either one). 0 is returned on success, -1 on error. + /// + /// order can be 'C' or 'F' or 'A' (for C-style or Fortran-style ordering or either one). + /// Buffer to copy to + public void ToContiguous(IntPtr buf, BufferOrderStyle order) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (Runtime.PythonVersion < new Version(3, 6)) + throw new NotSupportedException("ToContiguous requires at least Python 3.6"); + + if (Runtime.PyBuffer_ToContiguous(buf, ref _view, _view.len, order) < 0) + throw new PythonException(); + } + + /// + /// Fill the strides array with byte-strides of a contiguous (C-style if order is 'C' or Fortran-style if order is 'F') array of the given shape with the given number of bytes per element. + /// + public static void FillContiguousStrides(int ndims, IntPtr[] shape, IntPtr[] strides, int itemsize, BufferOrderStyle order) + { + Runtime.PyBuffer_FillContiguousStrides(ndims, shape, strides, itemsize, order); + } + + /// + /// FillInfo Method + /// + /// + /// Handle buffer requests for an exporter that wants to expose buf of size len with writability set according to readonly. buf is interpreted as a sequence of unsigned bytes. + /// The flags argument indicates the request type. This function always fills in view as specified by flags, unless buf has been designated as read-only and PyBUF_WRITABLE is set in flags. + /// On success, set view->obj to a new reference to exporter and return 0. Otherwise, raise PyExc_BufferError, set view->obj to NULL and return -1; + /// If this function is used as part of a getbufferproc, exporter MUST be set to the exporting object and flags must be passed unmodified.Otherwise, exporter MUST be NULL. + /// + /// On success, set view->obj to a new reference to exporter and return 0. Otherwise, raise PyExc_BufferError, set view->obj to NULL and return -1; + public void FillInfo(IntPtr exporter, IntPtr buf, long len, bool @readonly, PyBUF flags) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (Runtime.PyBuffer_FillInfo(ref _view, new BorrowedReference(exporter), buf, (IntPtr)len, @readonly, flags) < 0) + throw new PythonException(); + } + + /// + /// Writes a managed byte array into the buffer of a python object. This can be used to pass data like images from managed to python. + /// + public void Write(byte[] buffer, int offset, int count) + { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (ReadOnly) + throw new InvalidOperationException("Buffer is read-only"); + if ((long)_view.len > int.MaxValue) + throw new NotSupportedException("Python buffers bigger than int.MaxValue are not supported."); + if (count > buffer.Length) + throw new ArgumentOutOfRangeException("count", "Count is bigger than the buffer."); + if (count > (int)_view.len) + throw new ArgumentOutOfRangeException("count", "Count is bigger than the python buffer."); + if (_view.ndim != 1) + throw new NotSupportedException("Multidimensional arrays, scalars and objects without a buffer are not supported."); + + Marshal.Copy(buffer, offset, _view.buf, count); + } + + /// + /// Reads the buffer of a python object into a managed byte array. This can be used to pass data like images from python to managed. + /// + public int Read(byte[] buffer, int offset, int count) { + if (disposedValue) + throw new ObjectDisposedException(nameof(PyBuffer)); + if (count > buffer.Length) + throw new ArgumentOutOfRangeException("count", "Count is bigger than the buffer."); + if (_view.ndim != 1) + throw new NotSupportedException("Multidimensional arrays, scalars and objects without a buffer are not supported."); + if (_view.len.ToInt64() > int.MaxValue) + throw new NotSupportedException("Python buffers bigger than int.MaxValue are not supported."); + + int copylen = count < (int)_view.len ? count : (int)_view.len; + Marshal.Copy(_view.buf, buffer, offset, copylen); + return copylen; + } + + private bool disposedValue = false; // To detect redundant calls + + private void Dispose(bool disposing) + { + if (!disposedValue) { + Runtime.PyBuffer_Release(ref _view); + + _exporter = null; + Shape = null; + Strides = null; + SubOffsets = null; + + disposedValue = true; + } + } + + ~PyBuffer() + { + Dispose(false); + } + + /// + /// Release the buffer view and decrement the reference count for view->obj. This function MUST be called when the buffer is no longer being used, otherwise reference leaks may occur. + /// It is an error to call this function on a buffer that was not obtained via . + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 73d93e28a..adc5d4ebe 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -1096,6 +1096,21 @@ public override int GetHashCode() return ((ulong)Runtime.PyObject_Hash(obj)).GetHashCode(); } + /// + /// GetBuffer Method. This Method only works for objects that have a buffer (like "bytes", "bytearray" or "array.array") + /// + /// + /// Send a request to the PyObject to fill in view as specified by flags. If the PyObject cannot provide a buffer of the exact type, it MUST raise PyExc_BufferError, set view->obj to NULL and return -1. + /// On success, fill in view, set view->obj to a new reference to exporter and return 0. In the case of chained buffer providers that redirect requests to a single object, view->obj MAY refer to this object instead of exporter(See Buffer Object Structures). + /// Successful calls to must be paired with calls to , similar to malloc() and free(). Thus, after the consumer is done with the buffer, must be called exactly once. + /// + public PyBuffer GetBuffer(PyBUF flags = PyBUF.SIMPLE) + { + if (Runtime.PythonVersion < new Version(3, 5)) + throw new NotSupportedException("GetBuffer requires at least Python 3.5"); + return new PyBuffer(this, flags); + } + public long Refcount { diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 2f7fc9f7f..87b303ca7 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1049,6 +1049,46 @@ internal static long PyObject_Size(IntPtr pointer) internal static IntPtr PyObject_Dir(IntPtr pointer) => Delegates.PyObject_Dir(pointer); + //==================================================================== + // Python buffer API + //==================================================================== + + + internal static bool PyObject_CheckBuffer(BorrowedReference obj) + { + var type = PyObject_TYPE(obj); + var bufferProcs = Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.tp_as_buffer); + if (bufferProcs == IntPtr.Zero) return false; + var getBuffer = Marshal.ReadIntPtr(bufferProcs, 0); + return getBuffer != IntPtr.Zero; + } + + + internal static int PyObject_GetBuffer(BorrowedReference exporter, out Py_buffer view, PyBUF flags) => Delegates.PyObject_GetBuffer(exporter, out view, flags); + + + internal static void PyBuffer_Release(ref Py_buffer view) => Delegates.PyBuffer_Release(ref view); + + + internal static IntPtr PyBuffer_SizeFromFormat([MarshalAs(UnmanagedType.LPStr)] string format) => Delegates.PyBuffer_SizeFromFormat(format); + + + internal static int PyBuffer_IsContiguous(ref Py_buffer view, BufferOrderStyle order) => Delegates.PyBuffer_IsContiguous(ref view, order); + + + internal static IntPtr PyBuffer_GetPointer(ref Py_buffer view, IntPtr[] indices) => Delegates.PyBuffer_GetPointer(ref view, indices); + + + internal static int PyBuffer_FromContiguous(ref Py_buffer view, IntPtr buf, IntPtr len, BufferOrderStyle fort) => Delegates.PyBuffer_FromContiguous(ref view, buf, len, fort); + + + internal static int PyBuffer_ToContiguous(IntPtr buf, ref Py_buffer src, IntPtr len, BufferOrderStyle order) => Delegates.PyBuffer_ToContiguous(buf, ref src, len, order); + + + internal static void PyBuffer_FillContiguousStrides(int ndims, IntPtr[] shape, IntPtr[] strides, int itemsize, BufferOrderStyle order) => Delegates.PyBuffer_FillContiguousStrides(ndims, shape, strides, itemsize, order); + + + internal static int PyBuffer_FillInfo(ref Py_buffer view, BorrowedReference exporter, IntPtr buf, IntPtr len, bool @readonly, PyBUF flags) => Delegates.PyBuffer_FillInfo(ref view, exporter, buf, len, @readonly, flags); //==================================================================== // Python number API @@ -2073,6 +2113,16 @@ static Delegates() PyMethod_New = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyMethod_New), GetUnmanagedDll(PythonDLL))); Py_AddPendingCall = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_AddPendingCall), GetUnmanagedDll(PythonDLL))); Py_MakePendingCalls = GetDelegateForFunctionPointer(GetFunctionByName(nameof(Py_MakePendingCalls), GetUnmanagedDll(PythonDLL))); + PyObject_GetBuffer = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyObject_GetBuffer), GetUnmanagedDll(PythonDLL))); + PyBuffer_Release = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_Release), GetUnmanagedDll(PythonDLL))); + if (Runtime.PythonVersion >= new Version(3,9)) + PyBuffer_SizeFromFormat = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_SizeFromFormat), GetUnmanagedDll(PythonDLL))); + PyBuffer_IsContiguous = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_IsContiguous), GetUnmanagedDll(PythonDLL))); + PyBuffer_GetPointer = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_GetPointer), GetUnmanagedDll(PythonDLL))); + PyBuffer_FromContiguous = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_FromContiguous), GetUnmanagedDll(PythonDLL))); + PyBuffer_ToContiguous = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_ToContiguous), GetUnmanagedDll(PythonDLL))); + PyBuffer_FillContiguousStrides = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_FillContiguousStrides), GetUnmanagedDll(PythonDLL))); + PyBuffer_FillInfo = GetDelegateForFunctionPointer(GetFunctionByName(nameof(PyBuffer_FillInfo), GetUnmanagedDll(PythonDLL))); } static T GetDelegateForFunctionPointer(IntPtr functionPointer) { @@ -3250,6 +3300,51 @@ int updatepath // end of PY3 enum Py2 { } + + internal static PyObject_GetBufferDelegate PyObject_GetBuffer { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyObject_GetBufferDelegate(BorrowedReference exporter, out Py_buffer view, PyBUF flags); + + internal static PyBuffer_ReleaseDelegate PyBuffer_Release { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate void PyBuffer_ReleaseDelegate(ref Py_buffer view); + + internal static PyBuffer_SizeFromFormatDelegate PyBuffer_SizeFromFormat { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + internal delegate IntPtr PyBuffer_SizeFromFormatDelegate([MarshalAs(UnmanagedType.LPStr)] string format); + + internal static PyBuffer_IsContiguousDelegate PyBuffer_IsContiguous { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyBuffer_IsContiguousDelegate(ref Py_buffer view, BufferOrderStyle order); + + internal static PyBuffer_GetPointerDelegate PyBuffer_GetPointer { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate IntPtr PyBuffer_GetPointerDelegate(ref Py_buffer view, IntPtr[] indices); + + internal static PyBuffer_FromContiguousDelegate PyBuffer_FromContiguous { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyBuffer_FromContiguousDelegate(ref Py_buffer view, IntPtr buf, IntPtr len, BufferOrderStyle fort); + + internal static PyBuffer_ToContiguousDelegate PyBuffer_ToContiguous { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyBuffer_ToContiguousDelegate(IntPtr buf, ref Py_buffer src, IntPtr len, BufferOrderStyle order); + + internal static PyBuffer_FillContiguousStridesDelegate PyBuffer_FillContiguousStrides { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + public delegate void PyBuffer_FillContiguousStridesDelegate(int ndims, IntPtr[] shape, IntPtr[] strides, int itemsize, BufferOrderStyle order); + + internal static PyBuffer_FillInfoDelegate PyBuffer_FillInfo { get; } + + [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate int PyBuffer_FillInfoDelegate(ref Py_buffer view, BorrowedReference exporter, IntPtr buf, IntPtr len, bool @readonly, PyBUF flags); } } From 282842b2c56f94755c00e0691b0488d2b90036d6 Mon Sep 17 00:00:00 2001 From: SnGmng <38666407+SnGmng@users.noreply.github.com> Date: Fri, 29 May 2020 08:25:18 +0200 Subject: [PATCH 164/240] Update finalizer 2 --- src/runtime/pybuffer.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/runtime/pybuffer.cs b/src/runtime/pybuffer.cs index bcd7ed64e..84ef2bde8 100644 --- a/src/runtime/pybuffer.cs +++ b/src/runtime/pybuffer.cs @@ -6,7 +6,7 @@ namespace Python.Runtime { - public sealed class PyBuffer : IDisposable + public sealed class PyBuffer : IPyDisposable { private PyObject _exporter; private Py_buffer _view; @@ -197,7 +197,12 @@ public int Read(byte[] buffer, int offset, int count) { private void Dispose(bool disposing) { - if (!disposedValue) { + if (!disposedValue) + { + if (Runtime.Py_IsInitialized() == 0) + throw new InvalidOperationException("Python runtime must be initialized"); + + // this also decrements ref count for _view->obj Runtime.PyBuffer_Release(ref _view); _exporter = null; @@ -211,7 +216,11 @@ private void Dispose(bool disposing) ~PyBuffer() { - Dispose(false); + if (disposedValue) + { + return; + } + Finalizer.Instance.AddFinalizedObject(this); } /// @@ -223,5 +232,10 @@ public void Dispose() Dispose(true); GC.SuppressFinalize(this); } + + public IntPtr[] GetTrackedHandles() + { + return new IntPtr[] { _view.obj }; + } } } From 1e8806b0c0c1681bc137af1e886eedbdd2040a28 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 18:51:22 -0700 Subject: [PATCH 165/240] restricted license on Lost Tech fork --- LICENSE | 11 ++++++++++- pythonnet.15.sln | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 59abd9c81..e24150618 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,13 @@ -MIT License +This software is "code-available" to assist with Gradient debugging. +You must have a license for the matching version of Gradient (see +https://github.com/losttech/Gradient/) to access this source. Only +Gradient debugging is permitted. + +If you wish to obtain a version of this sofware with a more liberal +license, refer to https://github.com/pythonnet/pythonnet. + +This fork contains substantial parts of the original project, which are +distributed under the following MIT License: Copyright (c) 2006-2019 the contributors of the "Python for .NET" project diff --git a/pythonnet.15.sln b/pythonnet.15.sln index 12ccd4634..d561438c6 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{441A0123-F .editorconfig = .editorconfig .gitignore = .gitignore CHANGELOG.md = CHANGELOG.md + LICENSE = LICENSE README.rst = README.rst EndProjectSection EndProject From fa739a4cad1cad4d1b40cc25386421f4ac7ca133 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 18:54:18 -0700 Subject: [PATCH 166/240] implements buffer interface for .NET arrays of primitive types fixes https://github.com/losttech/Gradient/issues/27 --- .../{TestExample.cs => NumPyTests.cs} | 22 ++- src/embed_tests/TestPyBuffer.cs | 16 +- src/runtime/arrayobject.cs | 150 ++++++++++++++++++ src/runtime/bufferinterface.cs | 2 + src/runtime/exceptions.cs | 1 + src/runtime/typemanager.cs | 5 +- 6 files changed, 192 insertions(+), 4 deletions(-) rename src/embed_tests/{TestExample.cs => NumPyTests.cs} (63%) diff --git a/src/embed_tests/TestExample.cs b/src/embed_tests/NumPyTests.cs similarity index 63% rename from src/embed_tests/TestExample.cs rename to src/embed_tests/NumPyTests.cs index 671f9e33d..4c84905bb 100644 --- a/src/embed_tests/TestExample.cs +++ b/src/embed_tests/NumPyTests.cs @@ -2,15 +2,17 @@ using System.Collections.Generic; using NUnit.Framework; using Python.Runtime; +using Python.Runtime.Codecs; namespace Python.EmbeddingTest { - public class TestExample + public class NumPyTests { [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); + TupleCodec.Register(); } [OneTimeTearDown] @@ -49,5 +51,23 @@ public void TestReadme() Assert.AreEqual("[ 6. 10. 12.]", (a * b).ToString().Replace(" ", " ")); } + + [Test] + public void MultidimensionalNumPyArray() + { + PyObject np; + try { + np = Py.Import("numpy"); + } catch (PythonException) { + Assert.Inconclusive("Numpy or dependency not installed"); + return; + } + + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var ndarray = np.InvokeMethod("asarray", array.ToPython()); + Assert.AreEqual((2,2), ndarray.GetAttr("shape").As<(int,int)>()); + Assert.AreEqual(1, ndarray[(0, 0).ToPython()].As()); + Assert.AreEqual(array[1, 0], ndarray[(1, 0).ToPython()].As()); + } } } diff --git a/src/embed_tests/TestPyBuffer.cs b/src/embed_tests/TestPyBuffer.cs index 8ad3fb6f9..505fd1348 100644 --- a/src/embed_tests/TestPyBuffer.cs +++ b/src/embed_tests/TestPyBuffer.cs @@ -2,17 +2,19 @@ using System.Text; using NUnit.Framework; using Python.Runtime; +using Python.Runtime.Codecs; namespace Python.EmbeddingTest { public class TestPyBuffer { - [SetUp] + [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); + TupleCodec.Register(); } - [TearDown] + [OneTimeTearDown] public void Dispose() { PythonEngine.Shutdown(); @@ -69,5 +71,15 @@ public void TestBufferRead() } } } + + [Test] + public void ArrayHasBuffer() + { + var array = new[,] {{1, 2}, {3,4}}; + var memoryView = PythonEngine.Eval("memoryview"); + var mem = memoryView.Invoke(array.ToPython()); + Assert.AreEqual(1, mem[(0, 0).ToPython()].As()); + Assert.AreEqual(array[1,0], mem[(1, 0).ToPython()].As()); + } } } diff --git a/src/runtime/arrayobject.cs b/src/runtime/arrayobject.cs index 1ef318473..af82d4643 100644 --- a/src/runtime/arrayobject.cs +++ b/src/runtime/arrayobject.cs @@ -1,5 +1,7 @@ using System; using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace Python.Runtime { @@ -244,5 +246,153 @@ public static int sq_contains(IntPtr ob, IntPtr v) return 0; } + + #region Buffer protocol + static int GetBuffer(BorrowedReference obj, out Py_buffer buffer, PyBUF flags) + { + buffer = default; + + if (flags == PyBUF.SIMPLE) + { + Exceptions.SetError(Exceptions.BufferError, "SIMPLE not implemented"); + return -1; + } + if ((flags & PyBUF.F_CONTIGUOUS) == PyBUF.F_CONTIGUOUS) + { + Exceptions.SetError(Exceptions.BufferError, "only C-contiguous supported"); + return -1; + } + var self = (Array)((CLRObject)GetManagedObject(obj)).inst; + Type itemType = self.GetType().GetElementType(); + + bool formatRequested = (flags & PyBUF.FORMATS) != 0; + string format = formatRequested ? GetFormat(itemType) : null; + if (formatRequested && format is null) + { + Exceptions.SetError(Exceptions.BufferError, "unsupported element type: " + itemType.Name); + return -1; + } + var gcHandle = GCHandle.Alloc(self, GCHandleType.Pinned); + + int itemSize = Marshal.SizeOf(itemType); + IntPtr[] shape = GetShape(self); + IntPtr[] strides = GetStrides(shape, itemSize); + buffer = new Py_buffer + { + buf = gcHandle.AddrOfPinnedObject(), + obj = Runtime.SelfIncRef(obj.DangerousGetAddress()), + len = (IntPtr)(self.LongLength*itemSize), + itemsize = (IntPtr)itemSize, + _readonly = false, + ndim = self.Rank, + format = format, + shape = ToUnmanaged(shape), + strides = (flags & PyBUF.STRIDES) == PyBUF.STRIDES ? ToUnmanaged(strides) : IntPtr.Zero, + suboffsets = IntPtr.Zero, + _internal = (IntPtr)gcHandle, + }; + + return 0; + } + static void ReleaseBuffer(BorrowedReference obj, ref Py_buffer buffer) + { + if (buffer._internal == IntPtr.Zero) return; + + UnmanagedFree(ref buffer.shape); + UnmanagedFree(ref buffer.strides); + UnmanagedFree(ref buffer.suboffsets); + + var gcHandle = (GCHandle)buffer._internal; + gcHandle.Free(); + buffer._internal = IntPtr.Zero; + } + + static IntPtr[] GetStrides(IntPtr[] shape, long itemSize) + { + var result = new IntPtr[shape.Length]; + result[shape.Length - 1] = new IntPtr(itemSize); + for (int dim = shape.Length - 2; dim >= 0; dim--) + { + itemSize *= shape[dim + 1].ToInt64(); + result[dim] = new IntPtr(itemSize); + } + return result; + } + static IntPtr[] GetShape(Array array) + { + var result = new IntPtr[array.Rank]; + for (int i = 0; i < result.Length; i++) + result[i] = (IntPtr)array.GetLongLength(i); + return result; + } + + static void UnmanagedFree(ref IntPtr address) + { + if (address == IntPtr.Zero) return; + + Marshal.FreeHGlobal(address); + address = IntPtr.Zero; + } + static unsafe IntPtr ToUnmanaged(T[] array) where T : unmanaged + { + IntPtr result = Marshal.AllocHGlobal(checked(Marshal.SizeOf(typeof(T)) * array.Length)); + fixed (T* ptr = array) + { + var @out = (T*)result; + for (int i = 0; i < array.Length; i++) + @out[i] = ptr[i]; + } + return result; + } + + static readonly Dictionary ItemFormats = new Dictionary + { + [typeof(byte)] = "B", + [typeof(sbyte)] = "b", + + [typeof(bool)] = "?", + + [typeof(short)] = "h", + [typeof(ushort)] = "H", + [typeof(int)] = "i", + [typeof(uint)] = "I", + [typeof(long)] = "q", + [typeof(ulong)] = "Q", + + [typeof(IntPtr)] = "n", + [typeof(UIntPtr)] = "N", + + // TODO: half = "e" + [typeof(float)] = "f", + [typeof(double)] = "d", + }; + + static string GetFormat(Type elementType) + => ItemFormats.TryGetValue(elementType, out string result) ? result : null; + + static readonly GetBufferProc getBufferProc = GetBuffer; + static readonly ReleaseBufferProc releaseBufferProc = ReleaseBuffer; + static readonly IntPtr BufferProcsAddress = AllocateBufferProcs(); + static IntPtr AllocateBufferProcs() + { + var procs = new PyBufferProcs + { + Get = Marshal.GetFunctionPointerForDelegate(getBufferProc), + Release = Marshal.GetFunctionPointerForDelegate(releaseBufferProc), + }; + IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PyBufferProcs))); + Marshal.StructureToPtr(procs, result, fDeleteOld: false); + return result; + } + #endregion + + public static void InitializeSlots(IntPtr type, ISet initialized) + { + if (initialized.Add(nameof(TypeOffset.tp_as_buffer))) + { + // TODO: only for unmanaged arrays + TypeManager.InitializeSlot(type, BufferProcsAddress, nameof(TypeOffset.tp_as_buffer)); + } + } } } diff --git a/src/runtime/bufferinterface.cs b/src/runtime/bufferinterface.cs index fe6cb6746..f744acf7d 100644 --- a/src/runtime/bufferinterface.cs +++ b/src/runtime/bufferinterface.cs @@ -111,6 +111,8 @@ internal struct PyBufferProcs public IntPtr Release; } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int GetBufferProc(BorrowedReference obj, out Py_buffer buffer, PyBUF flags); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void ReleaseBufferProc(BorrowedReference obj, ref Py_buffer buffer); } diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 816633385..1c483e7e6 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -395,6 +395,7 @@ puplic static variables on the Exceptions class filled in from public static IntPtr AssertionError; public static IntPtr AttributeError; + public static IntPtr BufferError; public static IntPtr EOFError; public static IntPtr FloatingPointError; public static IntPtr EnvironmentError; diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index ddc9886ce..f8aafb998 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -771,6 +771,9 @@ internal static void InitializeSlots(IntPtr type, Type impl) seen.Add(name); } + var initSlot = impl.GetMethod("InitializeSlots", BindingFlags.Static | BindingFlags.Public); + initSlot?.Invoke(null, parameters: new object[] {type, seen}); + impl = impl.BaseType; } @@ -818,7 +821,7 @@ internal static void InitializeSlots(IntPtr type, Type impl) /// Type being initialized. /// Function pointer. /// Name of the method. - static void InitializeSlot(IntPtr type, IntPtr slot, string name) + internal static void InitializeSlot(IntPtr type, IntPtr slot, string name) { Type typeOffset = typeof(TypeOffset); FieldInfo fi = typeOffset.GetField(name); From cbbd4c4f5926df0feecc6f46b0f17ca9f7a78538 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 19:07:31 -0700 Subject: [PATCH 167/240] made new license info more prominent --- LICENSE | 23 ++--------------------- README.rst | 5 ++++- src/runtime/Python.Runtime.15.csproj | 2 ++ 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/LICENSE b/LICENSE index e24150618..0d2045bdd 100644 --- a/LICENSE +++ b/LICENSE @@ -7,24 +7,5 @@ If you wish to obtain a version of this sofware with a more liberal license, refer to https://github.com/pythonnet/pythonnet. This fork contains substantial parts of the original project, which are -distributed under the following MIT License: - -Copyright (c) 2006-2019 the contributors of the "Python for .NET" project - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +distributed under MIT License: +https://github.com/pythonnet/pythonnet/blob/master/LICENSE diff --git a/README.rst b/README.rst index 33e93c32a..7eec3f569 100644 --- a/README.rst +++ b/README.rst @@ -5,9 +5,12 @@ pythonnet - Python for .NET |github test shield| -|license shield| |nuget version| +|nuget version| |stackexchange shield| +This fork is part of `Gradient `_ and has a `different +license `_. + Python for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers. It diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 3c616cd1d..7adb659d6 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -5,6 +5,8 @@ Python.Runtime Python.Runtime Python.Runtime.UnofficialNetStandard + https://raw.githubusercontent.com/losttech/Gradient/master/LICENSE-TECH-PREVIEW.txt + This software is part of Gradient: https://losttech.software/gradient.html 3.0.0 true true From e6a614f0396c6cc14ba96dbd720f38d998e6968e Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 31 May 2020 20:12:56 -0700 Subject: [PATCH 168/240] don't expose array buffer interface with unsupported item types --- src/embed_tests/TestPyBuffer.cs | 9 +++++++++ src/runtime/arrayobject.cs | 5 ++++- src/runtime/typemanager.cs | 9 +++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/embed_tests/TestPyBuffer.cs b/src/embed_tests/TestPyBuffer.cs index 505fd1348..82e325269 100644 --- a/src/embed_tests/TestPyBuffer.cs +++ b/src/embed_tests/TestPyBuffer.cs @@ -81,5 +81,14 @@ public void ArrayHasBuffer() Assert.AreEqual(1, mem[(0, 0).ToPython()].As()); Assert.AreEqual(array[1,0], mem[(1, 0).ToPython()].As()); } + + [Test] + public void ReferenceTypeArrayHasNoBuffer() + { + var array = new[] {new object()}; + var memoryView = PythonEngine.Eval("memoryview"); + var error = Assert.Throws(() => memoryView.Invoke(array.ToPython())); + Assert.AreEqual("TypeError", error.PythonTypeName); + } } } diff --git a/src/runtime/arrayobject.cs b/src/runtime/arrayobject.cs index af82d4643..e489fbcff 100644 --- a/src/runtime/arrayobject.cs +++ b/src/runtime/arrayobject.cs @@ -388,7 +388,10 @@ static IntPtr AllocateBufferProcs() public static void InitializeSlots(IntPtr type, ISet initialized) { - if (initialized.Add(nameof(TypeOffset.tp_as_buffer))) + var gcHandle = (GCHandle)Marshal.ReadIntPtr(type, TypeOffset.magic()); + var self = (ArrayObject)gcHandle.Target; + if (ItemFormats.ContainsKey(self.type.GetElementType()) + && initialized.Add(nameof(TypeOffset.tp_as_buffer))) { // TODO: only for unmanaged arrays TypeManager.InitializeSlot(type, BufferProcsAddress, nameof(TypeOffset.tp_as_buffer)); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index f8aafb998..332b40fbb 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -130,6 +130,10 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Marshal.WriteIntPtr(type, TypeOffset.ob_type, Runtime.PyCLRMetaType); Runtime.XIncref(Runtime.PyCLRMetaType); + // Hide the gchandle of the implementation in a magic type slot. + GCHandle gc = GCHandle.Alloc(impl); + Marshal.WriteIntPtr(type, TypeOffset.magic(), (IntPtr)gc); + // add a __len__ slot for inheritors of ICollection and ICollection<> if (typeof(System.Collections.ICollection).IsAssignableFrom(clrType) || clrType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICollection<>))) { @@ -198,6 +202,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) if (Runtime.PyType_Ready(type) != 0) { + gc.Free(); return IntPtr.Zero; } @@ -206,10 +211,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) IntPtr mod = Runtime.PyString_FromString(mn); Runtime.PyDict_SetItemString(dict, "__module__", mod); - // Hide the gchandle of the implementation in a magic type slot. - GCHandle gc = GCHandle.Alloc(impl); - Marshal.WriteIntPtr(type, TypeOffset.magic(), (IntPtr)gc); - // Set the handle attributes on the implementing instance. impl.tpHandle = Runtime.PyCLRMetaType; impl.gcHandle = gc; From 4cd6f41551ce0820d83bc37e6786ba201983f531 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 1 Jun 2020 00:37:59 -0700 Subject: [PATCH 169/240] fixed codecs not affecting enums --- src/embed_tests/Codecs.cs | 23 ++++++++++++++++++++++- src/runtime/converter.cs | 5 ++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 6a0ce6bcd..2ddeb8a49 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -83,6 +83,22 @@ static void TupleRoundtripGeneric() { } } + [Test] + public void EnumEncoded() { + var enumEncoder = new FakeEncoder(); + PyObjectConversions.RegisterEncoder(enumEncoder); + ConsoleModifiers.Alt.ToPython(); + Assert.AreEqual(ConsoleModifiers.Alt, enumEncoder.LastObject); + } + + [Test] + public void EnumDecoded() { + var enumDecoder = new FakeDecoder(PythonEngine.Eval("list"), ConsoleModifiers.Alt); + PyObjectConversions.RegisterDecoder(enumDecoder); + var decoded = PythonEngine.Eval("[]").As(); + Assert.AreEqual(ConsoleModifiers.Alt, decoded); + } + const string TestExceptionMessage = "Hello World!"; [Test] public void ExceptionEncoded() { @@ -198,8 +214,13 @@ public bool TryDecode(PyObject pyObj, out T value) class FakeEncoder : IPyObjectEncoder { + public T LastObject { get; private set; } public bool CanEncode(Type type) => type == typeof(T); - public PyObject TryEncode(object value) => this.GetRawPythonProxy(); + public PyObject TryEncode(object value) + { + this.LastObject = (T)value; + return this.GetRawPythonProxy(); + } } class FakeDecoder : IPyObjectDecoder diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 4bb7a74fb..5c35bcf54 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -134,7 +134,7 @@ internal static IntPtr ToPython(object value, Type type) return result; } - if (Type.GetTypeCode(type) == TypeCode.Object && value.GetType() != typeof(object)) { + if (!type.IsPrimitive && value.GetType() != typeof(object)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; @@ -402,8 +402,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return false; } - TypeCode typeCode = Type.GetTypeCode(obType); - if (typeCode == TypeCode.Object) + if (!obType.IsPrimitive) { var pyType = new BorrowedReference(Runtime.PyObject_TYPE(value)); if (PyObjectConversions.TryDecode(new BorrowedReference(value), pyType, obType, out result)) From 104ee8cb0d36f1e5e48edb3816c0f17114336a36 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 1 Jun 2020 00:38:33 -0700 Subject: [PATCH 170/240] minor test changes --- src/embed_tests/Inspect.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/embed_tests/Inspect.cs b/src/embed_tests/Inspect.cs index 07e8be9be..e217d5b30 100644 --- a/src/embed_tests/Inspect.cs +++ b/src/embed_tests/Inspect.cs @@ -6,12 +6,12 @@ namespace Python.EmbeddingTest { public class Inspect { - [SetUp] + [OneTimeSetUp] public void SetUp() { PythonEngine.Initialize(); } - [TearDown] + [OneTimeTearDown] public void Dispose() { PythonEngine.Shutdown(); } From fe40b785555d2cefc22f504b610ad6129d76e889 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 1 Jun 2020 10:59:41 -0700 Subject: [PATCH 171/240] do not allow encoders for System.String --- src/runtime/converter.cs | 6 ++++-- src/runtime/converterextensions.cs | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 5c35bcf54..b8bd68280 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -134,7 +134,7 @@ internal static IntPtr ToPython(object value, Type type) return result; } - if (!type.IsPrimitive && value.GetType() != typeof(object)) { + if (EncodersAllowed(type)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { result = encoded.Handle; @@ -402,7 +402,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return false; } - if (!obType.IsPrimitive) + if (EncodersAllowed(obType)) { var pyType = new BorrowedReference(Runtime.PyObject_TYPE(value)); if (PyObjectConversions.TryDecode(new BorrowedReference(value), pyType, obType, out result)) @@ -419,6 +419,8 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return ToPrimitive(value, obType, out result, setError); } + static bool EncodersAllowed(Type type) => !type.IsPrimitive && type != typeof(string); + internal delegate bool TryConvertFromPythonDelegate(BorrowedReference pyObj, out object result); /// diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index 59b310f98..a8f394a2a 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -5,6 +5,8 @@ namespace Python.Runtime using System.Collections.Generic; using System.Linq; using System.Reflection; + using System.Runtime.CompilerServices; + using Python.Runtime.Codecs; /// @@ -128,6 +130,8 @@ internal static bool TryDecode(BorrowedReference obj, BorrowedReference objType, static Converter.TryConvertFromPythonDelegate GetDecoder(IntPtr sourceType, Type targetType) { + RuntimeHelpers.EnsureSufficientExecutionStack(); + IPyObjectDecoder decoder; var pyType = new PyObject(Runtime.SelfIncRef(sourceType)); lock (decoders) From fb2b5b1d862d52193987dcdc4308a788d73bd58d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 3 Jun 2020 00:02:52 -0700 Subject: [PATCH 172/240] fixed MappingMixin implementation (untested) --- src/runtime/Mixins/collections.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/Mixins/collections.py b/src/runtime/Mixins/collections.py index d38738295..f9299f951 100644 --- a/src/runtime/Mixins/collections.py +++ b/src/runtime/Mixins/collections.py @@ -34,10 +34,11 @@ class MutableSequenceMixin(SequenceMixin, col.MutableSequence): pass class MappingMixin(CollectionMixin, col.Mapping): + def __contains__(self, item): return self.ContainsKey(item) def keys(self): return self.Keys - def items(self): return self + def items(self): return [(k,self[k]) for k in self.Keys] def values(self): return self.Values - def __iter__(self): raise NotImplementedError + def __iter__(self): return self.Keys.__iter__() def get(self, key): _, item = self.TryGetValue(key) return item From b6d56b57103089e3174d3aa4d419c17bbd3d5fac Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 3 Jun 2020 15:34:48 -0700 Subject: [PATCH 173/240] basic tests for arrays and collection mixins --- src/embed_tests/Arrays.cs | 32 ++++++++++++++++++++++++ src/embed_tests/CollectionsMixins.cs | 37 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/embed_tests/Arrays.cs create mode 100644 src/embed_tests/CollectionsMixins.cs diff --git a/src/embed_tests/Arrays.cs b/src/embed_tests/Arrays.cs new file mode 100644 index 000000000..f71a87f9c --- /dev/null +++ b/src/embed_tests/Arrays.cs @@ -0,0 +1,32 @@ +namespace Python.EmbeddingTest { + using System; + using System.Linq; + + using NUnit.Framework; + + using Python.Runtime; + + public class Arrays { + [Test] + public void Enumerate() { + var objArray = new[] { new Uri("http://a"), new Uri("http://b") }; + using var scope = Py.CreateScope(); + scope.Set("arr", objArray); + scope.Set("s", ""); + scope.Exec("for item in arr: s += str(item)"); + var result = scope.Eval("s"); + Assert.AreEqual(string.Concat(args: objArray), result); + } + + + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + } +} diff --git a/src/embed_tests/CollectionsMixins.cs b/src/embed_tests/CollectionsMixins.cs new file mode 100644 index 000000000..18a521fad --- /dev/null +++ b/src/embed_tests/CollectionsMixins.cs @@ -0,0 +1,37 @@ +namespace Python.EmbeddingTest { + using System; + using System.Collections.Generic; + + using NUnit.Framework; + + using Python.Runtime; + + public class CollectionsMixins { + [Test] + public void Dict_Items_Iterable() { + var pyDict = this.dict.ToPython(); + var items = pyDict.InvokeMethod("items"); + using var scope = Py.CreateScope(); + scope.Set("iterator", this.Iter.Invoke(items)); + scope.Set("s", ""); + scope.Exec("for i in iterator: s += str(i)"); + } + + readonly Dictionary dict = new Dictionary { + ["42"] = new object(), + [new object()] = "21", + }; + readonly Lazy iter = new Lazy(() => PythonEngine.Eval("iter")); + PyObject Iter => this.iter.Value; + + [OneTimeSetUp] + public void SetUp() { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() { + PythonEngine.Shutdown(); + } + } +} From 89c7539ab9fa41cf355ff739450eb6ff7d39b30b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 3 Jun 2020 15:35:28 -0700 Subject: [PATCH 174/240] renamed package to LostTech.Python.Runtime --- README.rst | 4 ++-- src/runtime/Python.Runtime.15.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 7eec3f569..1b8f6f082 100644 --- a/README.rst +++ b/README.rst @@ -125,8 +125,8 @@ Some features are disabled in Python 3.8.0 because of .. |conda-forge version| image:: https://img.shields.io/conda/vn/conda-forge/pythonnet.svg :target: https://anaconda.org/conda-forge/pythonnet .. |github test shield| image:: https://github.com/losttech/pythonnet/workflows/Build%20%2B%20Test/badge.svg -.. |nuget version| image:: https://img.shields.io/nuget/vpre/Python.Runtime.UnofficialNetStandard - :target: https://www.nuget.org/packages/Python.Runtime.UnofficialNetStandard/ +.. |nuget version| image:: https://img.shields.io/nuget/vpre/LostTech.Python.Runtime + :target: https://www.nuget.org/packages/LostTech.Python.Runtime/ Resources --------- diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 7adb659d6..520ebda6f 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -4,7 +4,7 @@ AnyCPU Python.Runtime Python.Runtime - Python.Runtime.UnofficialNetStandard + LostTech.Python.Runtime https://raw.githubusercontent.com/losttech/Gradient/master/LICENSE-TECH-PREVIEW.txt This software is part of Gradient: https://losttech.software/gradient.html 3.0.0 From 0b0cb7e199808e6d79019cb9ab6a10973357fa87 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 10 Jun 2020 12:46:20 -0700 Subject: [PATCH 175/240] cleaned codecs tests up a bit --- src/embed_tests/Codecs.cs | 71 ++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index 2ddeb8a49..a01683392 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -5,6 +5,7 @@ namespace Python.EmbeddingTest { using NUnit.Framework; using Python.Runtime; using Python.Runtime.Codecs; + using static Python.Runtime.PyObjectConversions; public class Codecs { [SetUp] @@ -86,15 +87,17 @@ static void TupleRoundtripGeneric() { [Test] public void EnumEncoded() { var enumEncoder = new FakeEncoder(); - PyObjectConversions.RegisterEncoder(enumEncoder); + RegisterEncoder(enumEncoder); ConsoleModifiers.Alt.ToPython(); Assert.AreEqual(ConsoleModifiers.Alt, enumEncoder.LastObject); } [Test] public void EnumDecoded() { - var enumDecoder = new FakeDecoder(PythonEngine.Eval("list"), ConsoleModifiers.Alt); - PyObjectConversions.RegisterDecoder(enumDecoder); + var enumDecoder = new DecoderReturningPredefinedValue( + objectType: PythonEngine.Eval("list"), + decodeResult: ConsoleModifiers.Alt); + RegisterDecoder(enumDecoder); var decoded = PythonEngine.Eval("[]").As(); Assert.AreEqual(ConsoleModifiers.Alt, decoded); } @@ -102,7 +105,7 @@ public void EnumDecoded() { const string TestExceptionMessage = "Hello World!"; [Test] public void ExceptionEncoded() { - PyObjectConversions.RegisterEncoder(new ValueErrorCodec()); + RegisterEncoder(new ValueErrorCodec()); void CallMe() => throw new ValueErrorWrapper(TestExceptionMessage); var callMeAction = new Action(CallMe); using var _ = Py.GIL(); @@ -121,7 +124,7 @@ def call(func): [Test] public void ExceptionDecoded() { - PyObjectConversions.RegisterDecoder(new ValueErrorCodec()); + RegisterDecoder(new ValueErrorCodec()); using var _ = Py.GIL(); using var scope = Py.CreateScope(); var error = Assert.Throws(() => PythonEngine.Exec( @@ -131,7 +134,7 @@ public void ExceptionDecoded() { [Test] public void ExceptionDecodedNoInstance() { - PyObjectConversions.RegisterDecoder(new InstancelessExceptionDecoder()); + RegisterDecoder(new InstancelessExceptionDecoder()); using var _ = Py.GIL(); using var scope = Py.CreateScope(); var error = Assert.Throws(() => PythonEngine.Exec( @@ -141,7 +144,7 @@ public void ExceptionDecodedNoInstance() { [Test] public void ExceptionStringValue() { - PyObjectConversions.RegisterDecoder(new AttributeErrorDecoder()); + RegisterDecoder(new AttributeErrorDecoder()); using var _ = Py.GIL(); using var scope = Py.CreateScope(); var error = Assert.Throws(() => "hi".ToPython().GetAttr("blah")); @@ -223,29 +226,6 @@ public PyObject TryEncode(object value) } } - class FakeDecoder : IPyObjectDecoder - { - public PyObject TheOnlySupportedSourceType { get; } - public TTarget DecodeResult { get; } - - public FakeDecoder(PyObject objectType, TTarget decodeResult) - { - this.TheOnlySupportedSourceType = objectType; - this.DecodeResult = decodeResult; - } - - public bool CanDecode(PyObject objectType, Type targetType) - => objectType.Handle == TheOnlySupportedSourceType.Handle - && targetType == typeof(TTarget); - public bool TryDecode(PyObject pyObj, out T value) - { - if (typeof(T) != typeof(TTarget)) - throw new ArgumentException(nameof(T)); - value = (T)(object)DecodeResult; - return true; - } - } - /// /// "Decodes" only objects of exact type . /// Result is just a raw Python object proxy. @@ -256,25 +236,40 @@ class ObjectToRawProxyEncoder : IPyObjectEncoder public PyObject TryEncode(object value) => this.GetRawPythonProxy(); } + abstract class SingleTypeDecoder : IPyObjectDecoder + { + public PyObject LastSourceType { get; private set; } + public PyObject TheOnlySupportedSourceType { get; } + + public virtual bool CanDecode(PyObject objectType, Type targetType) + { + this.LastSourceType = objectType; + return objectType.Handle == this.TheOnlySupportedSourceType.Handle; + } + + public abstract bool TryDecode(PyObject pyObj, out T value); + + protected SingleTypeDecoder(PyObject objectType) { + this.TheOnlySupportedSourceType = objectType; + } + } + /// /// Decodes object of specified Python type to the predefined value /// /// Type of the - class DecoderReturningPredefinedValue : IPyObjectDecoder + class DecoderReturningPredefinedValue : SingleTypeDecoder { - public PyObject TheOnlySupportedSourceType { get; } public TTarget DecodeResult { get; } - public DecoderReturningPredefinedValue(PyObject objectType, TTarget decodeResult) + public DecoderReturningPredefinedValue(PyObject objectType, TTarget decodeResult) : base(objectType) { - this.TheOnlySupportedSourceType = objectType; this.DecodeResult = decodeResult; } - public bool CanDecode(PyObject objectType, Type targetType) - => objectType.Handle == TheOnlySupportedSourceType.Handle - && targetType == typeof(TTarget); - public bool TryDecode(PyObject pyObj, out T value) + public override bool CanDecode(PyObject objectType, Type targetType) + => base.CanDecode(objectType, targetType) && targetType == typeof(TTarget); + public override bool TryDecode(PyObject pyObj, out T value) { if (typeof(T) != typeof(TTarget)) throw new ArgumentException(nameof(T)); From 224199394616c4801a8280a67375e49e45603ea6 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 10 Jun 2020 12:50:16 -0700 Subject: [PATCH 176/240] introduced Runtime.RefCountSanityLimit --- src/runtime/runtime.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 87b303ca7..ed8dc01db 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -597,6 +597,12 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) return types; } + /// + /// Raise an exception when a refcount of Python object exceeds this limit. + /// Only affects debug builds. + /// + public static long RefCountSanityLimit { get; set; } = Int32.MaxValue; + /// /// Managed exports of the Python C API. Where appropriate, we do /// some optimization to avoid managed <--> unmanaged transitions @@ -605,11 +611,11 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) internal static unsafe void XIncref(IntPtr op) { DebugUtil.EnsureGIL(); -#if DEBUG if (op == IntPtr.Zero) throw new ArgumentNullException(nameof(op)); +#if DEBUG long refcount = Refcount(op); - if (refcount < 0 || refcount > 100000) + if (refcount < 0 || refcount > RefCountSanityLimit) throw new ArgumentOutOfRangeException( message: "Reference count is insane", paramName: nameof(op), @@ -651,7 +657,7 @@ internal static unsafe void XDecref(IntPtr op) if (op == IntPtr.Zero) throw new ArgumentNullException(nameof(op)); long refcount = Refcount(op); - if (refcount <= 0 || refcount > 100000) + if (refcount <= 0 || refcount > RefCountSanityLimit) throw new ArgumentOutOfRangeException( paramName: nameof(refcount), actualValue: refcount, From 869c8801648f8d0041cb534af917c35203849d54 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 10 Jun 2020 13:00:47 -0700 Subject: [PATCH 177/240] don't remove outer exception from Iterator.__next__ --- src/runtime/iterator.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/runtime/iterator.cs b/src/runtime/iterator.cs index 0c749df53..d380f20ad 100644 --- a/src/runtime/iterator.cs +++ b/src/runtime/iterator.cs @@ -33,10 +33,6 @@ public static IntPtr tp_iternext(IntPtr ob) } catch (Exception e) { - if (e.InnerException != null) - { - e = e.InnerException; - } Exceptions.SetError(e); return IntPtr.Zero; } From 4f2e7bb3176f2ab9f6bb68111a289892bc4fb7f4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 11 Jun 2020 19:28:17 -0700 Subject: [PATCH 178/240] fixed bad CLR type name handling in TypeManager --- src/runtime/typemanager.cs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 332b40fbb..301fc1d60 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -234,27 +234,31 @@ static void GetPythonTypeName(Type clrType, System.Text.StringBuilder target) { string fullName = clrType.GetGenericTypeDefinition().FullName; int argCountIndex = fullName.LastIndexOf('`'); - string nonGenericFullName = fullName.Substring(0, argCountIndex); - string nonGenericName = CleanupFullName(nonGenericFullName); - target.Append(nonGenericName); - - var arguments = clrType.GetGenericArguments(); - target.Append('<'); - for (int argIndex = 0; argIndex < arguments.Length; argIndex++) + if (argCountIndex >= 0) { - if (argIndex != 0) + string nonGenericFullName = fullName.Substring(0, argCountIndex); + string nonGenericName = CleanupFullName(nonGenericFullName); + target.Append(nonGenericName); + + var arguments = clrType.GetGenericArguments(); + target.Append('<'); + for (int argIndex = 0; argIndex < arguments.Length; argIndex++) { - target.Append(','); + if (argIndex != 0) + { + target.Append(','); + } + + GetPythonTypeName(arguments[argIndex], target); } - GetPythonTypeName(arguments[argIndex], target); + + target.Append('>'); + return; } - target.Append('>'); - } - else - { - string name = CleanupFullName(clrType.FullName); - target.Append(name); } + + string name = CleanupFullName(clrType.FullName); + target.Append(name); } static string CleanupFullName(string fullTypeName) From 23355c8d1eea6c9484e57a149d9005a294c79ac6 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 11 Jun 2020 19:28:45 -0700 Subject: [PATCH 179/240] added a test for ability to iterate over LINQ enumerables from Python --- src/embed_tests/CollectionsMixins.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/CollectionsMixins.cs b/src/embed_tests/CollectionsMixins.cs index 18a521fad..7ac0a5cfb 100644 --- a/src/embed_tests/CollectionsMixins.cs +++ b/src/embed_tests/CollectionsMixins.cs @@ -1,12 +1,19 @@ namespace Python.EmbeddingTest { using System; using System.Collections.Generic; - + using System.Linq; using NUnit.Framework; using Python.Runtime; public class CollectionsMixins { + [Test] + public void Enumerables_Iterable() { + var iterable = Enumerable.Repeat(42, 5).ToPython(); + var iterator = iterable.InvokeMethod("__iter__"); + int first = iterator.InvokeMethod("__next__").As(); + Assert.AreEqual(42, first); + } [Test] public void Dict_Items_Iterable() { var pyDict = this.dict.ToPython(); From 0aa2adf67233e8eb6c5f1689362402f51b5e55c4 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 11 Jun 2020 19:30:09 -0700 Subject: [PATCH 180/240] fixed dynamic unary and binary operations not raising Python exception on failure Instead, they crashed with ArgumentNullException due to null pointer passed to PyObject constructor. Fixed by adding a null check. --- src/runtime/pyobject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index adc5d4ebe..610876e23 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -1387,6 +1387,7 @@ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg result = null; return false; } + Exceptions.ErrorCheck(res); result = CheckNone(new PyObject(res)); return true; } @@ -1440,6 +1441,7 @@ public override bool TryUnaryOperation(UnaryOperationBinder binder, out object r result = null; return false; } + Exceptions.ErrorCheck(res); result = CheckNone(new PyObject(res)); return true; } From c0c947953951c4642c665df742ae35ca3451d69b Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 12 Jun 2020 14:54:20 -0700 Subject: [PATCH 181/240] fixed TupleCodec not properly calling element codecs --- src/runtime/Codecs/TupleCodecs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs index 6c5c816a8..4fa79e04c 100644 --- a/src/runtime/Codecs/TupleCodecs.cs +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -35,7 +35,7 @@ public PyObject TryEncode(object value) foreach (FieldInfo field in tupleType.GetFields()) { var item = field.GetValue(value); - IntPtr pyItem = Converter.ToPython(item); + IntPtr pyItem = Converter.ToPython(item, item?.GetType() ?? field.FieldType); Runtime.PyTuple_SetItem(tuple, fieldIndex, pyItem); fieldIndex++; } From d919a183aea55ed46b5b6950aae58f672720d93f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 15 Jun 2020 17:43:52 -0700 Subject: [PATCH 182/240] removed Obsolete warnings from Codec-related classes --- src/runtime/Codecs/DecoderGroup.cs | 3 --- src/runtime/Codecs/EncoderGroup.cs | 3 --- src/runtime/converterextensions.cs | 1 - 3 files changed, 7 deletions(-) diff --git a/src/runtime/Codecs/DecoderGroup.cs b/src/runtime/Codecs/DecoderGroup.cs index 8a290d5d4..cc511ed50 100644 --- a/src/runtime/Codecs/DecoderGroup.cs +++ b/src/runtime/Codecs/DecoderGroup.cs @@ -8,7 +8,6 @@ namespace Python.Runtime.Codecs /// /// Represents a group of s. Useful to group them by priority. /// - [Obsolete(Util.UnstableApiMessage)] public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable { readonly List decoders = new List(); @@ -49,7 +48,6 @@ public bool TryDecode(PyObject pyObj, out T value) IEnumerator IEnumerable.GetEnumerator() => this.decoders.GetEnumerator(); } - [Obsolete(Util.UnstableApiMessage)] public static class DecoderGroupExtensions { /// @@ -58,7 +56,6 @@ public static class DecoderGroupExtensions /// that can decode from to , /// or null if a matching decoder can not be found. /// - [Obsolete(Util.UnstableApiMessage)] public static IPyObjectDecoder GetDecoder( this IPyObjectDecoder decoder, PyObject objectType, Type targetType) diff --git a/src/runtime/Codecs/EncoderGroup.cs b/src/runtime/Codecs/EncoderGroup.cs index a5708c0bb..4f776a669 100644 --- a/src/runtime/Codecs/EncoderGroup.cs +++ b/src/runtime/Codecs/EncoderGroup.cs @@ -8,7 +8,6 @@ namespace Python.Runtime.Codecs /// /// Represents a group of s. Useful to group them by priority. /// - [Obsolete(Util.UnstableApiMessage)] public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable { readonly List encoders = new List(); @@ -50,7 +49,6 @@ public PyObject TryEncode(object value) IEnumerator IEnumerable.GetEnumerator() => this.encoders.GetEnumerator(); } - [Obsolete(Util.UnstableApiMessage)] public static class EncoderGroupExtensions { /// @@ -58,7 +56,6 @@ public static class EncoderGroupExtensions /// (potentially selecting one from a collection), /// that can encode the specified . /// - [Obsolete(Util.UnstableApiMessage)] public static IEnumerable GetEncoders(this IPyObjectEncoder decoder, Type type) { if (decoder is null) throw new ArgumentNullException(nameof(decoder)); diff --git a/src/runtime/converterextensions.cs b/src/runtime/converterextensions.cs index a8f394a2a..7f911966b 100644 --- a/src/runtime/converterextensions.cs +++ b/src/runtime/converterextensions.cs @@ -47,7 +47,6 @@ public interface IPyObjectEncoder /// This class allows to register additional marshalling codecs. /// Python.NET will pick suitable encoder/decoder registered first /// - [Obsolete(Util.UnstableApiMessage)] public static class PyObjectConversions { static readonly DecoderGroup decoders = new DecoderGroup(); From 604f4897c0e7832f885d6c768676674be669c0af Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 15 Jun 2020 17:44:30 -0700 Subject: [PATCH 183/240] removed Finalizer.Enable --- src/embed_tests/TestFinalizer.cs | 60 -------------------------------- src/runtime/finalizer.cs | 17 ++------- 2 files changed, 3 insertions(+), 74 deletions(-) diff --git a/src/embed_tests/TestFinalizer.cs b/src/embed_tests/TestFinalizer.cs index f82767af1..219f3a566 100644 --- a/src/embed_tests/TestFinalizer.cs +++ b/src/embed_tests/TestFinalizer.cs @@ -34,8 +34,6 @@ private static void FullGCCollect() [Test] public void CollectBasicObject() { - Assert.IsTrue(Finalizer.Instance.Enable); - Finalizer.Instance.Threshold = 1; bool called = false; var objectCount = 0; @@ -95,64 +93,6 @@ private static void MakeAGarbage(out WeakReference shortWeak, out WeakReference obj = null; } - private static long CompareWithFinalizerOn(PyObject pyCollect, bool enbale) - { - // Must larger than 512 bytes make sure Python use - string str = new string('1', 1024); - Finalizer.Instance.Enable = true; - FullGCCollect(); - FullGCCollect(); - pyCollect.Invoke(); - Finalizer.Instance.Collect(); - Finalizer.Instance.Enable = enbale; - - // Estimate unmanaged memory size - long before = Environment.WorkingSet - GC.GetTotalMemory(true); - for (int i = 0; i < 10000; i++) - { - // Memory will leak when disable Finalizer - new PyString(str); - } - FullGCCollect(); - FullGCCollect(); - pyCollect.Invoke(); - if (enbale) - { - Finalizer.Instance.Collect(); - } - - FullGCCollect(); - FullGCCollect(); - long after = Environment.WorkingSet - GC.GetTotalMemory(true); - return after - before; - - } - - /// - /// Because of two vms both have their memory manager, - /// this test only prove the finalizer has take effect. - /// - [Test] - [Ignore("Too many uncertainties, only manual on when debugging")] - public void SimpleTestMemory() - { - bool oldState = Finalizer.Instance.Enable; - try - { - using (PyObject gcModule = PythonEngine.ImportModule("gc")) - using (PyObject pyCollect = gcModule.GetAttr("collect")) - { - long span1 = CompareWithFinalizerOn(pyCollect, false); - long span2 = CompareWithFinalizerOn(pyCollect, true); - Assert.Less(span2, span1); - } - } - finally - { - Finalizer.Instance.Enable = oldState; - } - } - class MyPyObject : PyObject { public MyPyObject(IntPtr op) : base(op) diff --git a/src/runtime/finalizer.cs b/src/runtime/finalizer.cs index 0eb50cf22..59c208b7e 100644 --- a/src/runtime/finalizer.cs +++ b/src/runtime/finalizer.cs @@ -24,9 +24,7 @@ public class ErrorArgs : EventArgs public event EventHandler CollectOnce; public event EventHandler ErrorHandler; - public int Threshold { get; set; } - [Obsolete("Finalizer will always be enabled in the future")] - public bool Enable { get; set; } + public int Threshold { get; set; } = 200; private ConcurrentQueue _objQueue = new ConcurrentQueue(); private int _throttled; @@ -68,11 +66,7 @@ public IncorrectRefCountException(IntPtr ptr) #endregion - private Finalizer() - { - Enable = true; - Threshold = 200; - } + private Finalizer() { } [Obsolete("forceDispose parameter is unused. All objects are disposed regardless.")] public void Collect(bool forceDispose) => this.DisposeAll(); @@ -81,7 +75,7 @@ private Finalizer() internal void ThrottledCollect() { _throttled = unchecked(this._throttled + 1); - if (!Enable || _throttled < Threshold) return; + if (_throttled < Threshold) return; _throttled = 0; this.Collect(); } @@ -93,11 +87,6 @@ public List GetCollectedObjects() internal void AddFinalizedObject(IPyDisposable obj) { - if (!Enable) - { - return; - } - #if FINALIZER_CHECK lock (_queueLock) #endif From 9f0746b4552dfa4faf8135ab615c3dffc310f835 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 15 Jun 2020 18:26:08 -0700 Subject: [PATCH 184/240] removed #if PYTHONxxx conditionals to match --- src/runtime/importhook.cs | 3 +-- src/runtime/interop38.cs | 21 +-------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index b16c8d2c1..043cf4de1 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -112,12 +112,11 @@ internal static void Shutdown() bool shouldFreeDef = Runtime.Refcount(py_clr_module) == 1; Runtime.XDecref(py_clr_module); py_clr_module = IntPtr.Zero; -#if PYTHON3 + if (shouldFreeDef) { ReleaseModuleDef(); } -#endif Runtime.XDecref(root.pyHandle); root = null; diff --git a/src/runtime/interop38.cs b/src/runtime/interop38.cs index 9126bca6a..aac8fedd4 100644 --- a/src/runtime/interop38.cs +++ b/src/runtime/interop38.cs @@ -3,7 +3,6 @@ // DO NOT MODIFY BY HAND. -#if PYTHON38 using System; using System.Collections; using System.Collections.Specialized; @@ -14,24 +13,8 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + internal static class TypeOffset38 { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; @@ -148,5 +131,3 @@ public static int magic() public static int members = 0; } } - -#endif From de4c3fb6b3867843273ed6a4c2c1f1bc46b77a38 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 15 Jun 2020 19:47:33 -0700 Subject: [PATCH 185/240] changed the base type of PyScope to PyObject also added validation to public PyScope methods, and fixed potential crush in PyScope.Set --- src/runtime/pyscope.cs | 131 +++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index eed13677e..1a1e296ec 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -22,24 +22,16 @@ public class PyGILAttribute : Attribute } [PyGIL] - public class PyScope : DynamicObject, IPyDisposable + public class PyScope : PyObject, IPyDisposable { - public readonly string Name; - - /// - /// the python Module object the scope associated with. - /// - internal readonly IntPtr obj; + public string Name { get; } /// /// the variable dict of the scope. /// - internal readonly IntPtr variables; + internal IntPtr variables; internal BorrowedReference VarsReference => new BorrowedReference(variables); - private bool _isDisposed; - private bool _finalized = false; - /// /// The Manager this scope associated with. /// It provides scopes this scope can import. @@ -57,16 +49,19 @@ public class PyScope : DynamicObject, IPyDisposable /// /// Create a scope based on a Python Module. /// - internal PyScope(IntPtr ptr, PyScopeManager manager) + internal PyScope(IntPtr ptr, PyScopeManager manager): base(ptr) { if (!Runtime.PyType_IsSubtype(Runtime.PyObject_TYPE(ptr), Runtime.PyModuleType)) { throw new PyScopeException("object is not a module"); } Manager = manager ?? PyScopeManager.Global; - obj = ptr; //Refcount of the variables not increase variables = Runtime.PyModule_GetDict(obj); + if (variables == IntPtr.Zero) + { + throw new ArgumentException(message: "Scope does not have '__dict__'"); + } Runtime.CheckExceptionOccurred(); Runtime.PyDict_SetItemString( @@ -82,6 +77,8 @@ internal PyScope(IntPtr ptr, PyScopeManager manager) /// public PyDict Variables() { + this.EnsureNotDisposed(); + Runtime.XIncref(variables); return new PyDict(variables); } @@ -92,6 +89,8 @@ public PyDict Variables() /// public PyScope NewScope() { + this.EnsureNotDisposed(); + var scope = Manager.Create(); scope.ImportAll(this); return scope; @@ -106,7 +105,9 @@ public PyScope NewScope() /// public dynamic Import(string name, string asname = null) { - Check(); + if (name is null) throw new ArgumentNullException(nameof(name)); + this.EnsureNotDisposed(); + if (String.IsNullOrEmpty(asname)) { asname = name; @@ -134,7 +135,9 @@ public dynamic Import(string name, string asname = null) /// public void Import(PyScope scope, string asname) { - this.Set(asname, scope.obj); + if (scope is null) throw new ArgumentNullException(nameof(scope)); + + this.SetInternal(asname, scope.Reference); } /// @@ -146,6 +149,8 @@ public void Import(PyScope scope, string asname) /// public void Import(PyObject module, string asname = null) { + if (module is null) throw new ArgumentNullException(nameof(module)); + if (String.IsNullOrEmpty(asname)) { asname = module.GetAttr("__name__").As(); @@ -162,6 +167,8 @@ public void Import(PyObject module, string asname = null) /// public void ImportAll(string name) { + if (name is null) throw new ArgumentNullException(nameof(name)); + PyScope scope; Manager.TryGet(name, out scope); if (scope != null) @@ -184,6 +191,9 @@ public void ImportAll(string name) /// public void ImportAll(PyScope scope) { + if (scope is null) throw new ArgumentNullException(nameof(scope)); + this.EnsureNotDisposed(); + int result = Runtime.PyDict_Update(variables, scope.variables); if (result < 0) { @@ -199,10 +209,13 @@ public void ImportAll(PyScope scope) /// public void ImportAll(PyObject module) { + if (module is null) throw new ArgumentNullException(nameof(module)); + this.EnsureNotDisposed(); if (Runtime.PyObject_Type(module.obj) != Runtime.PyModuleType) { throw new PyScopeException("object is not a module"); } + var module_dict = Runtime.PyModule_GetDict(module.obj); int result = Runtime.PyDict_Update(variables, module_dict); if (result < 0) @@ -219,6 +232,9 @@ public void ImportAll(PyObject module) /// public void ImportAll(PyDict dict) { + if (dict is null) throw new ArgumentNullException(nameof(dict)); + this.EnsureNotDisposed(); + int result = Runtime.PyDict_Update(variables, dict.obj); if (result < 0) { @@ -235,7 +251,9 @@ public void ImportAll(PyDict dict) /// public PyObject Execute(PyObject script, PyDict locals = null) { - Check(); + if (script is null) throw new ArgumentNullException(nameof(script)); + this.EnsureNotDisposed(); + IntPtr _locals = locals == null ? variables : locals.obj; IntPtr ptr = Runtime.PyEval_EvalCode(script.Handle, variables, _locals); Runtime.CheckExceptionOccurred(); @@ -257,14 +275,12 @@ public PyObject Execute(PyObject script, PyDict locals = null) /// public T Execute(PyObject script, PyDict locals = null) { - Check(); PyObject pyObj = Execute(script, locals); if (pyObj == null) { return default(T); } - var obj = pyObj.As(); - return obj; + return pyObj.As(); } /// @@ -276,7 +292,8 @@ public T Execute(PyObject script, PyDict locals = null) /// public PyObject Eval(string code, PyDict locals = null) { - Check(); + this.EnsureNotDisposed(); + IntPtr _locals = locals == null ? variables : locals.obj; var flag = (IntPtr)Runtime.Py_eval_input; @@ -303,10 +320,8 @@ public PyObject Eval(string code, PyDict locals = null) /// public T Eval(string code, PyDict locals = null) { - Check(); PyObject pyObj = Eval(code, locals); - var obj = pyObj.As(); - return obj; + return pyObj.As(); } /// @@ -317,13 +332,14 @@ 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); } private void Exec(string code, IntPtr _globals, IntPtr _locals) { + this.EnsureNotDisposed(); + var flag = (IntPtr)Runtime.Py_file_input; NewReference reference = Runtime.PyRun_String( code, flag, _globals, _locals @@ -352,17 +368,25 @@ private void Exec(string code, IntPtr _globals, IntPtr _locals) /// public void Set(string name, object value) { + this.EnsureNotDisposed(); + IntPtr _value = Converter.ToPython(value, value?.GetType()); - Set(name, _value); - Runtime.XDecref(_value); + try + { + this.SetInternal(name, new BorrowedReference(_value)); + } + finally + { + Runtime.XDecref(_value); + } } - private void Set(string name, IntPtr value) + private void SetInternal(string name, BorrowedReference value) { - Check(); + this.EnsureNotDisposed(); using (var pyKey = new PyString(name)) { - int r = Runtime.PyObject_SetItem(variables, pyKey.obj, value); + int r = Runtime.PyObject_SetItem(variables, pyKey.obj, value.DangerousGetAddress()); if (r < 0) { throw PythonException.ThrowLastAsClrException(); @@ -378,7 +402,8 @@ private void Set(string name, IntPtr value) /// public void Remove(string name) { - Check(); + this.EnsureNotDisposed(); + using (var pyKey = new PyString(name)) { int r = Runtime.PyObject_DelItem(variables, pyKey.obj); @@ -397,7 +422,8 @@ public void Remove(string name) /// public bool Contains(string name) { - Check(); + this.EnsureNotDisposed(); + using (var pyKey = new PyString(name)) { return Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0; @@ -431,7 +457,8 @@ public PyObject Get(string name) /// public bool TryGet(string name, out PyObject value) { - Check(); + this.EnsureNotDisposed(); + using (var pyKey = new PyString(name)) { if (Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0) @@ -467,7 +494,8 @@ public bool TryGet(string name, out PyObject value) /// public T Get(string name) { - Check(); + this.EnsureNotDisposed(); + PyObject pyObj = Get(name); if (pyObj == null) { @@ -486,7 +514,8 @@ public T Get(string name) /// public bool TryGet(string name, out T value) { - Check(); + this.EnsureNotDisposed(); + PyObject pyObj; var result = TryGet(name, out pyObj); if (!result) @@ -522,38 +551,24 @@ public override bool TrySetMember(SetMemberBinder binder, object value) return true; } - private void Check() + private void EnsureNotDisposed() { - if (_isDisposed) + if (this.obj == IntPtr.Zero) { - throw new PyScopeException($"The scope of name '{Name}' object has been disposed"); + throw new ObjectDisposedException( + objectName: this.Name, + message: $"The scope object has been disposed"); } } - public void Dispose() + protected override void Dispose(bool disposing) { - if (_isDisposed) + this.variables = IntPtr.Zero; + if (disposing) { - return; - } - _isDisposed = true; - Runtime.XDecref(obj); - this.OnDispose?.Invoke(this); - } - - public IntPtr[] GetTrackedHandles() - { - return new IntPtr[] { obj }; - } - - ~PyScope() - { - if (_finalized || _isDisposed) - { - return; + this.OnDispose?.Invoke(this); } - _finalized = true; - Finalizer.Instance.AddFinalizedObject(this); + base.Dispose(disposing); } } From d6efc72a59d0932a55cdcf0225d61020c9e9ee2a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Mon, 15 Jun 2020 20:37:09 -0700 Subject: [PATCH 186/240] tests: InstancelessExceptionDecoder constructor requires GIL --- src/embed_tests/Codecs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index f5e445f5c..ac986c9f0 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -134,8 +134,8 @@ public void ExceptionDecoded() { [Test] public void ExceptionDecodedNoInstance() { - RegisterDecoder(new InstancelessExceptionDecoder()); using var _ = Py.GIL(); + RegisterDecoder(new InstancelessExceptionDecoder()); using var scope = Py.CreateScope(); var error = Assert.Throws(() => PythonEngine.Exec( $"[].__iter__().__next__()")); From be72bd488af206680a48e47da725f63775f93c08 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 16 Jun 2020 13:56:06 -0700 Subject: [PATCH 187/240] fixed TypeOffset loading for Python 3.8 --- src/runtime/typeoffset.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/runtime/typeoffset.cs b/src/runtime/typeoffset.cs index 173ce0ea0..1da7ec281 100644 --- a/src/runtime/typeoffset.cs +++ b/src/runtime/typeoffset.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Specialized; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Reflection; @@ -22,7 +23,11 @@ static TypeOffset() for (int i = 0; i < fi.Length; i++) { fi[i].SetValue(null, i * size); - typeOffset.GetField(fi[i].Name).SetValue(null, i * size); + var field = typeOffset.GetField(fi[i].Name); + if (field is null) + Debug.WriteLine("ignoring field " + fi[i].Name); + else + field.SetValue(null, i * size); } } From 74e7d626f2e18d1f239c712bb7bcedb1ebc61288 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 16 Jun 2020 15:13:32 -0700 Subject: [PATCH 188/240] fixed crash due to unnecessary decref of a borrowed reference in params array handling --- src/runtime/methodbinder.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index da91289ac..15f50478d 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -375,7 +375,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference) { isNewReference = false; - IntPtr op; + IntPtr op; // for a params method, we may have a sequence or single/multiple items // here we look to see if the item at the paramIndex is there or not // and then if it is a sequence itself. @@ -393,10 +393,6 @@ static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out { isNewReference = true; op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount); - if (item != IntPtr.Zero) - { - Runtime.XDecref(item); - } } } else From ec76b1fb885bdcfea3fbb06da2d22071412a8eb5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 16 Jun 2020 15:23:21 -0700 Subject: [PATCH 189/240] enable overriding Python DLL in embed tests via PYTHON_DLL_PATH --- src/embed_tests/GlobalTestsSetup.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/embed_tests/GlobalTestsSetup.cs b/src/embed_tests/GlobalTestsSetup.cs index b3261bd0c..8f4981476 100644 --- a/src/embed_tests/GlobalTestsSetup.cs +++ b/src/embed_tests/GlobalTestsSetup.cs @@ -17,6 +17,12 @@ public void ConfigureRuntime() { if (Path.IsPathFullyQualified(Runtime.PythonDLL)) return; + string pyDll = Environment.GetEnvironmentVariable("PYTHON_DLL_PATH"); + if (!string.IsNullOrEmpty(pyDll)) + { + Runtime.PythonDLL = pyDll; + } + string pyVer = Environment.GetEnvironmentVariable("PYTHON_VERSION"); if (!string.IsNullOrEmpty(pyVer)) { @@ -26,7 +32,7 @@ public void ConfigureRuntime() string pyHome = Environment.GetEnvironmentVariable("PYTHON_HOME") // defined in GitHub action setup-python ?? Environment.GetEnvironmentVariable("pythonLocation"); - if (!string.IsNullOrEmpty(pyHome)) + if (!string.IsNullOrEmpty(pyHome) && !Path.IsPathFullyQualified(Runtime.PythonDLL)) { string dll = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Path.Combine(pyHome, Runtime.PythonDLL) From 83586f2a96ab4d6bef347987f5072558ce3fd7d8 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 16 Jun 2020 19:12:56 -0700 Subject: [PATCH 190/240] fixed implementation of mixins for Mapping and MutableMapping (still untested) --- src/runtime/Mixins/collections.py | 38 +++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/runtime/Mixins/collections.py b/src/runtime/Mixins/collections.py index f9299f951..e89db6208 100644 --- a/src/runtime/Mixins/collections.py +++ b/src/runtime/Mixins/collections.py @@ -39,24 +39,44 @@ def keys(self): return self.Keys def items(self): return [(k,self[k]) for k in self.Keys] def values(self): return self.Values def __iter__(self): return self.Keys.__iter__() - def get(self, key): - _, item = self.TryGetValue(key) - return item + def get(self, key, default=None): + existed, item = self.TryGetValue(key) + return item if existed else default class MutableMappingMixin(MappingMixin, col.MutableMapping): + _UNSET_ = object() + def __delitem__(self, key): - return self.Remove(key) + self.Remove(key) + def clear(self): self.Clear() - def pop(self, key): - return self.Remove(key) - def setdefault(self, key, value): + + def pop(self, key, default=_UNSET_): + existed, item = self.TryGetValue(key) + if existed: + self.Remove(key) + return item + elif default == self._UNSET_: + raise KeyError(key) + else: + return default + + def setdefault(self, key, value=None): existed, item = self.TryGetValue(key) if existed: return item else: self[key] = value return value - def update(self, items): - for key, value in items: + + def update(self, items, **kwargs): + if isinstance(items, col.Mapping): + for key, value in items.items(): + self[key] = value + else: + for key, value in items: + self[key] = value + + for key, value in kwargs.items(): self[key] = value From e8932947d11acffe8eb8bc1d61b50580eb55f06a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 16 Jun 2020 23:25:37 -0700 Subject: [PATCH 191/240] fixed mixin calls to TryGetValue --- src/runtime/Mixins/collections.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/Mixins/collections.py b/src/runtime/Mixins/collections.py index e89db6208..a82032472 100644 --- a/src/runtime/Mixins/collections.py +++ b/src/runtime/Mixins/collections.py @@ -36,11 +36,11 @@ class MutableSequenceMixin(SequenceMixin, col.MutableSequence): class MappingMixin(CollectionMixin, col.Mapping): def __contains__(self, item): return self.ContainsKey(item) def keys(self): return self.Keys - def items(self): return [(k,self[k]) for k in self.Keys] + def items(self): return [(k,self.get(k)) for k in self.Keys] def values(self): return self.Values def __iter__(self): return self.Keys.__iter__() def get(self, key, default=None): - existed, item = self.TryGetValue(key) + existed, item = self.TryGetValue(key, None) return item if existed else default class MutableMappingMixin(MappingMixin, col.MutableMapping): @@ -53,7 +53,7 @@ def clear(self): self.Clear() def pop(self, key, default=_UNSET_): - existed, item = self.TryGetValue(key) + existed, item = self.TryGetValue(key, None) if existed: self.Remove(key) return item @@ -63,7 +63,7 @@ def pop(self, key, default=_UNSET_): return default def setdefault(self, key, value=None): - existed, item = self.TryGetValue(key) + existed, item = self.TryGetValue(key, None) if existed: return item else: From 25aa4bce3e282f88128df8cfd19ff55917321765 Mon Sep 17 00:00:00 2001 From: danbarzilian Date: Wed, 17 Jun 2020 04:31:41 -0400 Subject: [PATCH 192/240] Increase ob's ref count in tp_repr to avoid accidental free --- AUTHORS.md | 1 + CHANGELOG.md | 2 ++ src/runtime/classbase.cs | 1 + 3 files changed, 4 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 163a42860..3b9d5534b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -74,4 +74,5 @@ - ([@SnGmng](https://github.com/SnGmng)) - ([@stonebig](https://github.com/stonebig)) - ([@testrunner123](https://github.com/testrunner123)) +- ([@DanBarzilian](https://github.com/DanBarzilian)) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad4016450..afb2badbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Fixed +- Fix incorrect dereference of wrapper object in tp_repr, which may result in a program crash + ## [2.5.0][] - 2020-06-14 This version improves performance on benchmarks significantly compared to 2.3. diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs index 30aef4ced..115dc097f 100644 --- a/src/runtime/classbase.cs +++ b/src/runtime/classbase.cs @@ -266,6 +266,7 @@ public static IntPtr tp_repr(IntPtr ob) //otherwise use the standard object.__repr__(inst) IntPtr args = Runtime.PyTuple_New(1); + Runtime.XIncref(ob); Runtime.PyTuple_SetItem(args, 0, ob); IntPtr reprFunc = Runtime.PyObject_GetAttrString(Runtime.PyBaseObjectType, "__repr__"); var output = Runtime.PyObject_Call(reprFunc, args, IntPtr.Zero); From dcbd03c2390b8b0870977d108b3f79e3a2d6e00e Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:36:27 -0700 Subject: [PATCH 193/240] InteropConfiguration.Default => MakeDefault() --- src/runtime/InteropConfiguration.cs | 2 +- src/runtime/pythonengine.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/InteropConfiguration.cs b/src/runtime/InteropConfiguration.cs index f3afa13a7..2924f776c 100644 --- a/src/runtime/InteropConfiguration.cs +++ b/src/runtime/InteropConfiguration.cs @@ -10,7 +10,7 @@ internal readonly PythonBaseTypeProviderGroup pythonBaseTypeProviders = new PythonBaseTypeProviderGroup(); public IList PythonBaseTypeProviders => this.pythonBaseTypeProviders; - public static InteropConfiguration Default => new InteropConfiguration + public static InteropConfiguration MakeDefault() => new InteropConfiguration { PythonBaseTypeProviders = { diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index c25e42fcd..a8e59b5bf 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -18,7 +18,7 @@ public class PythonEngine : IDisposable private static IntPtr _pythonHome = IntPtr.Zero; private static IntPtr _programName = IntPtr.Zero; private static IntPtr _pythonPath = IntPtr.Zero; - private static InteropConfiguration interopConfiguration = InteropConfiguration.Default; + private static InteropConfiguration interopConfiguration = InteropConfiguration.MakeDefault(); public PythonEngine() { @@ -373,7 +373,7 @@ public static void Shutdown() initialized = false; - InteropConfiguration = InteropConfiguration.Default; + InteropConfiguration = InteropConfiguration.MakeDefault(); } } From 8f06e4ca0271b3762358ed4ebf154d4b4088b70a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:38:20 -0700 Subject: [PATCH 194/240] PyIter is now IEnumerator instead of IEnumerator --- src/runtime/pyiter.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index 368ac57df..8841a471c 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -9,7 +9,7 @@ namespace Python.Runtime /// PY3: https://docs.python.org/3/c-api/iterator.html /// for details. /// - public class PyIter : PyObject, IEnumerator + public class PyIter : PyObject, IEnumerator { private PyObject _current; @@ -34,7 +34,7 @@ protected override void Dispose(bool disposing) public bool MoveNext() { - var next = Runtime.PyIter_Next(Reference); + using var next = Runtime.PyIter_Next(Reference); if (next.IsNull()) { // dispose of the previous object, if there was one @@ -51,9 +51,7 @@ public void Reset() throw new NotSupportedException(); } - public object Current - { - get { return _current; } - } + public PyObject Current => _current; + object System.Collections.IEnumerator.Current => this.Current; } } From 145be415478393191f0dabded988943c8be79310 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:44:58 -0700 Subject: [PATCH 195/240] corrected a few error checks in PythonEngine --- src/runtime/pythonengine.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index a8e59b5bf..79acca0a3 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -262,7 +262,8 @@ static BorrowedReference DefineModule(string name) var module = Runtime.PyImport_AddModule(name); var module_globals = Runtime.PyModule_GetDict(module); var builtins = Runtime.PyEval_GetBuiltins(); - Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); + int r = Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins); + PythonException.ThrowIfIsNotZero(r); return module; } @@ -519,7 +520,7 @@ public static void EndAllowThreads(IntPtr ts) public static PyObject ImportModule(string name) { IntPtr op = Runtime.PyImport_ImportModule(name); - Runtime.CheckExceptionOccurred(); + Exceptions.ErrorCheck(op); return new PyObject(op); } @@ -534,7 +535,7 @@ public static PyObject ImportModule(string name) public static PyObject ReloadModule(PyObject module) { IntPtr op = Runtime.PyImport_ReloadModule(module.Handle); - Runtime.CheckExceptionOccurred(); + Exceptions.ErrorCheck(op); return new PyObject(op); } @@ -549,9 +550,9 @@ public static PyObject ReloadModule(PyObject module) public static PyObject ModuleFromString(string name, string code) { IntPtr c = Runtime.Py_CompileString(code, "none", (int)RunFlagType.File); - Runtime.CheckExceptionOccurred(); + Exceptions.ErrorCheck(c); IntPtr m = Runtime.PyImport_ExecCodeModule(name, c); - Runtime.CheckExceptionOccurred(); + Exceptions.ErrorCheck(c); return new PyObject(m); } @@ -559,7 +560,7 @@ public static PyObject Compile(string code, string filename = "", RunFlagType mo { var flag = (int)mode; IntPtr ptr = Runtime.Py_CompileString(code, filename, flag); - Runtime.CheckExceptionOccurred(); + Exceptions.ErrorCheck(ptr); return new PyObject(ptr); } From 3f3789b4921620baee179ce9a2ffc61a176a29ba Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:48:17 -0700 Subject: [PATCH 196/240] immediately dispose PyErr instance after it's been decoded --- src/runtime/pythonexception.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 0db435d5d..3eab8ab47 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -144,12 +144,16 @@ static Exception FromPyErr(BorrowedReference pyTypeHandle, BorrowedReference pyV if (!pyValueHandle.IsNull) errorDict["value"] = new PyObject(pyValueHandle); if (!pyTracebackHandle.IsNull) errorDict["traceback"] = new PyObject(pyTracebackHandle); + object decoded; + var pyErrType = Runtime.InteropModule.GetAttr("PyErr"); - var pyErrInfo = pyErrType.Invoke(new PyTuple(), errorDict); - if (PyObjectConversions.TryDecode(pyErrInfo.Reference, pyErrType.Reference, - typeof(Exception), out object decoded) && decoded is Exception decodedPyErrInfo) + using (PyObject pyErrInfo = pyErrType.Invoke(new PyTuple(), errorDict)) { - return decodedPyErrInfo; + if (PyObjectConversions.TryDecode(pyErrInfo.Reference, pyErrType.Reference, + typeof(Exception), out decoded) && decoded is Exception decodedPyErrInfo) + { + return decodedPyErrInfo; + } } if (!pyTypeHandle.IsNull) From 9fabf4e1199a744d6f148d00f36c2281a3c66b8e Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:49:49 -0700 Subject: [PATCH 197/240] simplify disposal of PythonException --- src/runtime/pythonexception.cs | 52 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 3eab8ab47..dfca2c70c 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -17,8 +17,6 @@ public class PythonException : System.Exception, IPyDisposable private string _traceback = ""; private string _message = ""; private string _pythonTypeName = ""; - private bool disposed = false; - private bool _finalized = false; [Obsolete("Please, use FromPyErr instead")] public PythonException() @@ -225,11 +223,10 @@ static string TracebackHandleToString(BorrowedReference tracebackHandle) { ~PythonException() { - if (_finalized || disposed) + if (this.IsDisposed) { return; } - _finalized = true; Finalizer.Instance.AddFinalizedObject(this); } @@ -361,34 +358,35 @@ public string Format() /// public void Dispose() { - if (!disposed) + if (this.IsDisposed) + return; + + if (Runtime.Py_IsInitialized() == 0) + throw new InvalidOperationException("Python runtime must be initialized"); + + if (!Runtime.IsFinalizing) { - if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing) + if (_pyType != IntPtr.Zero) { - IntPtr gs = PythonEngine.AcquireLock(); - if (_pyType != IntPtr.Zero) - { - Runtime.XDecref(_pyType); - _pyType= IntPtr.Zero; - } + Runtime.XDecref(_pyType); + _pyType= IntPtr.Zero; + } - if (_pyValue != IntPtr.Zero) - { - Runtime.XDecref(_pyValue); - _pyValue = IntPtr.Zero; - } + if (_pyValue != IntPtr.Zero) + { + Runtime.XDecref(_pyValue); + _pyValue = IntPtr.Zero; + } - // XXX Do we ever get TraceBack? // - if (_pyTB != IntPtr.Zero) - { - Runtime.XDecref(_pyTB); - _pyTB = IntPtr.Zero; - } - PythonEngine.ReleaseLock(gs); + // XXX Do we ever get TraceBack? // + if (_pyTB != IntPtr.Zero) + { + Runtime.XDecref(_pyTB); + _pyTB = IntPtr.Zero; } - GC.SuppressFinalize(this); - disposed = true; } + + GC.SuppressFinalize(this); } public IntPtr[] GetTrackedHandles() @@ -396,6 +394,8 @@ public IntPtr[] GetTrackedHandles() return new IntPtr[] { _pyType, _pyValue, _pyTB }; } + bool IsDisposed => _pyType == IntPtr.Zero && _pyValue == IntPtr.Zero && _pyTB == IntPtr.Zero; + /// /// Matches Method /// From 33bc9a6bf6b3843658511f3736ecc68ff568ed17 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:52:05 -0700 Subject: [PATCH 198/240] minor changes in PyTuple --- src/runtime/pytuple.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 716fc4249..e7c1d234a 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -35,15 +35,14 @@ public PyTuple(PyObject o):base(FromPyObject(o)) { } - static IntPtr FromPyObject(PyObject o) + static BorrowedReference FromPyObject(PyObject o) { if (o == null) throw new ArgumentNullException(nameof(o)); if (!IsTupleType(o)) { throw new ArgumentException("object is not a tuple"); } - Runtime.XIncref(o.obj); - return o.obj; + return o.Reference; } @@ -77,6 +76,7 @@ static IntPtr FromItems(PyObject[] items) int count = items.Length; IntPtr obj = Runtime.PyTuple_New(count); + Exceptions.ErrorCheck(obj); try { for (var i = 0; i < count; i++) { if (items[i] == null) throw new ArgumentNullException(); From 152900055dc84d3fd9a3dd04e189faeeeb2626f1 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 12:56:20 -0700 Subject: [PATCH 199/240] avoid dynamic in TestInstanceWrapping --- src/embed_tests/TestInstanceWrapping.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs index 202288750..7c6be134b 100644 --- a/src/embed_tests/TestInstanceWrapping.cs +++ b/src/embed_tests/TestInstanceWrapping.cs @@ -57,8 +57,8 @@ public void OverloadResolution_ParamsTypeMatch() { using (Py.GIL()) { var o = overloaded.ToPython(); - dynamic callWithInts = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, 43)"); - callWithInts(o); + var callWithInts = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, 43)"); + callWithInts.Invoke(o); Assert.AreEqual(42, overloaded.Value); } } @@ -69,8 +69,8 @@ public void OverloadResolution_ParamsTypeMisMatch() { using (Py.GIL()) { var o = overloaded.ToPython(); - dynamic callWithIntAndStr = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, object())"); - var error = Assert.Throws(() => callWithIntAndStr(o), "Should have thrown PythonException"); + var callWithIntAndStr = PythonEngine.Eval($"lambda o: o.{nameof(Overloaded.ArgPlusParams)}(42, object())"); + var error = Assert.Throws(() => callWithIntAndStr.Invoke(o), "Should have thrown PythonException"); Assert.AreEqual(expected: Exceptions.TypeError, actual: error.PyType, "Should have thrown TypeError"); } } From 02fae43620da7b18dd3d142314ffa9efeecf5e4d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:01:18 -0700 Subject: [PATCH 200/240] dispose objects in a few iterable tests --- src/embed_tests/TestRuntime.cs | 35 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs index fefeb945f..2dd308f9e 100644 --- a/src/embed_tests/TestRuntime.cs +++ b/src/embed_tests/TestRuntime.cs @@ -83,19 +83,23 @@ public static void PyCheck_Iter_PyObject_IsIterable_Test() Runtime.Runtime.Py_Initialize(); // Tests that a python list is an iterable, but not an iterator - var pyList = NewReference.DangerousFromPointer(Runtime.Runtime.PyList_New(0)); - Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyList)); - Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyList)); + using (var pyList = NewReference.DangerousFromPointer(Runtime.Runtime.PyList_New(0))) + { + Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyList)); + Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyList)); - // Tests that a python list iterator is both an iterable and an iterator - var pyListIter = Runtime.Runtime.PyObject_GetIter(pyList); - Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyListIter)); - Assert.IsTrue(Runtime.Runtime.PyIter_Check(pyListIter)); + // Tests that a python list iterator is both an iterable and an iterator + using var pyListIter = Runtime.Runtime.PyObject_GetIter(pyList); + Assert.IsTrue(Runtime.Runtime.PyObject_IsIterable(pyListIter)); + Assert.IsTrue(Runtime.Runtime.PyIter_Check(pyListIter)); + } // Tests that a python float is neither an iterable nor an iterator - var pyFloat = NewReference.DangerousFromPointer(Runtime.Runtime.PyFloat_FromDouble(2.73)); - Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(pyFloat)); - Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyFloat)); + using (var pyFloat = NewReference.DangerousFromPointer(Runtime.Runtime.PyFloat_FromDouble(2.73))) + { + Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(pyFloat)); + Assert.IsFalse(Runtime.Runtime.PyIter_Check(pyFloat)); + } Runtime.Runtime.Py_Finalize(); } @@ -115,11 +119,14 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test() if (lockType == IntPtr.Zero) throw new KeyNotFoundException("class 'Lock' was not found in 'threading'"); - var lockInstance = NewReference.DangerousFromPointer(Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0))); - Exceptions.ErrorCheck(lockInstance); + using (var lockInstance = NewReference.DangerousFromPointer( + Runtime.Runtime.PyObject_CallObject(lockType, Runtime.Runtime.PyTuple_New(0)))) + { + Exceptions.ErrorCheck(lockInstance); - Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance)); - Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance)); + Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance)); + Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance)); + } Runtime.Runtime.Py_Finalize(); } From 76e688737ba1c088d24405792797ccb3b3c9f82d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:43:24 -0700 Subject: [PATCH 201/240] return typed references from GetTypeHandle --- src/runtime/classderived.cs | 2 +- src/runtime/classmanager.cs | 7 ++++--- src/runtime/clrobject.cs | 21 ++++++++++---------- src/runtime/constructorbinding.cs | 5 ++--- src/runtime/extensiontype.cs | 27 +++++++++++++++----------- src/runtime/interop.cs | 2 ++ src/runtime/metatype.cs | 2 +- src/runtime/methodbinding.cs | 14 ++++++++------ src/runtime/moduleobject.cs | 4 ++-- src/runtime/runtime.cs | 9 ++++++--- src/runtime/typemanager.cs | 32 ++++++++++++++++--------------- 11 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index 568abf173..b6f0a2581 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -820,7 +820,7 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, objec try { // create the python object - IntPtr type = TypeManager.GetTypeHandle(obj.GetType()); + BorrowedReference type = TypeManager.GetTypeHandle(obj.GetType()); self = new CLRObject(obj, type); // set __pyobj__ to self and deref the python object which will allow this diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index 9aaa75a59..43168e598 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -132,12 +132,13 @@ private static void InitClassBase(Type type, ClassBase impl) // managed type, filling the Python type slots with thunks that // point to the managed methods providing the implementation. - IntPtr tp = TypeManager.GetTypeHandle(impl, type); + BorrowedReference tp = TypeManager.GetTypeHandle(impl, type); Exceptions.ErrorCheck(tp); - impl.tpHandle = tp; + #warning this overwrites existing value when type == typeof(object). Why ? Lifetimes ??? + impl.tpHandle = tp.DangerousGetAddress(); // Finally, initialize the class __dict__ and return the object. - IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict); + IntPtr dict = Marshal.ReadIntPtr(tp.DangerousGetAddress(), TypeOffset.tp_dict); IDictionaryEnumerator iter = info.members.GetEnumerator(); diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 6089f18ff..04ba74862 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -7,38 +7,39 @@ internal class CLRObject : ManagedType { internal object inst; - internal CLRObject(object ob, IntPtr tp) + internal CLRObject(object ob, BorrowedReference tp) { - IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); + NewReference py = Runtime.PyType_GenericAlloc(tp, 0); - var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); + var flags = (TypeFlags)Util.ReadCLong(tp.DangerousGetAddress(), TypeOffset.tp_flags); if ((flags & TypeFlags.Subclass) != 0) { - IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp)); + IntPtr dict = Marshal.ReadIntPtr(py.DangerousGetAddress(), ObjectOffset.TypeDictOffset(tp)); if (dict == IntPtr.Zero) { dict = Runtime.PyDict_New(); - Marshal.WriteIntPtr(py, ObjectOffset.TypeDictOffset(tp), dict); + Marshal.WriteIntPtr(py.DangerousGetAddress(), ObjectOffset.TypeDictOffset(tp), dict); } } - tpHandle = tp; - pyHandle = py; + // it is safe to "borrow" type pointer, because we also own a reference to an instance + tpHandle = tp.DangerousGetAddress(); + pyHandle = py.DangerousMoveToPointer(); GCHandle gc = GCHandle.Alloc(this); int gcHandleOffset = ObjectOffset.ReflectedObjectGCHandle(this.Instance); - Marshal.WriteIntPtr(py, gcHandleOffset, (IntPtr)gc); + Marshal.WriteIntPtr(pyHandle, gcHandleOffset, (IntPtr)gc); gcHandle = gc; inst = ob; // Fix the BaseException args (and __cause__ in case of Python 3) // slot if wrapping a CLR exception - Exceptions.SetArgsAndCause(py); + Exceptions.SetArgsAndCause(pyHandle); } static CLRObject GetInstance(object ob, IntPtr pyType) { - return new CLRObject(ob, pyType); + return new CLRObject(ob, new BorrowedReference(pyType)); } diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs index 3908628b9..839215cc7 100644 --- a/src/runtime/constructorbinding.cs +++ b/src/runtime/constructorbinding.cs @@ -26,11 +26,10 @@ internal class ConstructorBinding : ExtensionType private ConstructorBinder ctorBinder; private IntPtr repr; - public ConstructorBinding(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder) + public ConstructorBinding(Type type, BorrowedReference pyTypeHndl, ConstructorBinder ctorBinder) { this.type = type; - Runtime.XIncref(pyTypeHndl); - this.pyTypeHndl = pyTypeHndl; + this.pyTypeHndl = pyTypeHndl.DangerousIncRefOrNull(); this.ctorBinder = ctorBinder; repr = IntPtr.Zero; } diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index 713babbd6..b7f4996ca 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Runtime.InteropServices; namespace Python.Runtime @@ -17,7 +18,7 @@ public ExtensionType() // The Python instance object is related to an instance of a // particular concrete subclass with a hidden CLR gchandle. - IntPtr tp = TypeManager.GetTypeHandle(GetType()); + BorrowedReference tp = TypeManager.GetTypeHandle(GetType()); //int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt); //if (rc > 1050) @@ -26,22 +27,22 @@ public ExtensionType() // DebugUtil.DumpType(tp); //} - IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); + using var py = Runtime.PyType_GenericAlloc(tp, 0); GCHandle gc = GCHandle.Alloc(this); - Marshal.WriteIntPtr(py, ObjectOffset.GetDefaultGCHandleOffset(), (IntPtr)gc); + Marshal.WriteIntPtr(py.DangerousGetAddress(), ObjectOffset.GetDefaultGCHandleOffset(), (IntPtr)gc); + + // It is safe to store the reference to the type without incref, + // because we also hold an instance of that type. + tpHandle = tp.DangerousGetAddress(); + pyHandle = py.DangerousMoveToPointer(); + gcHandle = gc; // We have to support gc because the type machinery makes it very // hard not to - but we really don't have a need for it in most // concrete extension types, so untrack the object to save calls // from Python into the managed runtime that are pure overhead. - - Runtime.PyObject_GC_UnTrack(py); - - // Steals a ref to tpHandle. - tpHandle = tp; - pyHandle = py; - gcHandle = gc; + Runtime.PyObject_GC_UnTrack(pyHandle); } @@ -50,8 +51,12 @@ public ExtensionType() /// public static void FinalizeObject(ExtensionType self) { + Debug.Assert(self.pyHandle != IntPtr.Zero); Runtime.PyObject_GC_Del(self.pyHandle); - // Not necessary for decref of `tpHandle`. + self.pyHandle = IntPtr.Zero; + + self.tpHandle = IntPtr.Zero; + self.gcHandle.Free(); } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index c107f32ed..0b1347d42 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -111,6 +111,8 @@ internal static void ClrGcHandleOffsetAssertSanity(int offset) /// /// Returns dict offset in instances of the specified /// + public static int TypeDictOffset(BorrowedReference type) + => TypeDictOffset(type.DangerousGetAddress()); public static int TypeDictOffset(IntPtr type) { Debug.Assert(Runtime.PyType_Check(type)); return Runtime.PyType_IsSubtype(type, Exceptions.BaseException) diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index fa8beeae1..69b769293 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -87,7 +87,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) { if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")) { - return TypeManager.CreateSubType(name, base_type, dict); + return TypeManager.CreateSubType(name, base_type, dict).DangerousIncRefOrNull(); } } } diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index d7a47317e..bab905208 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -16,6 +16,7 @@ internal class MethodBinding : ExtensionType internal MethodObject m; internal IntPtr target; internal IntPtr targetType; + internal BorrowedReference TargetReference => new BorrowedReference(this.target); public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) { @@ -115,7 +116,9 @@ public int Compare(Type a, Type b) { } static MethodBinding GetInstance(IntPtr ob) - => GetManagedObject(new BorrowedReference(ob)); + => GetInstance(new BorrowedReference(ob)); + static MethodBinding GetInstance(BorrowedReference ob) + => GetManagedObject(ob); /// /// MethodBinding __getattribute__ implementation. @@ -225,15 +228,14 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) if (baseType != null) { string baseMethodName = "_" + baseType.type.Name + "__" + self.m.name; - IntPtr baseMethod = Runtime.PyObject_GetAttrString(target, baseMethodName); - if (baseMethod != IntPtr.Zero) + using var baseMethod = Runtime.PyObject_GetAttrString(self.TargetReference, baseMethodName); + if (!baseMethod.IsNull()) { - IntPtr baseMethodType = Runtime.PyObject_TYPE(baseMethod); - IntPtr methodBindingTypeHandle = TypeManager.GetTypeHandle(typeof(MethodBinding)); + BorrowedReference baseMethodType = Runtime.PyObject_TYPE(baseMethod); + BorrowedReference methodBindingTypeHandle = TypeManager.GetTypeHandle(typeof(MethodBinding)); if (baseMethodType == methodBindingTypeHandle) { self = GetInstance(baseMethod); - Runtime.XDecref(baseMethod); } } else diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index 80b55dfd2..f3efbb2a9 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -45,11 +45,11 @@ public ModuleObject(string name) IntPtr pyname = Runtime.PyString_FromString(moduleName); IntPtr pyfilename = Runtime.PyString_FromString(filename); IntPtr pydocstring = Runtime.PyString_FromString(docstring); - IntPtr pycls = TypeManager.GetTypeHandle(GetType()); + BorrowedReference pycls = TypeManager.GetTypeHandle(GetType()); Runtime.PyDict_SetItemString(dict, "__name__", pyname); Runtime.PyDict_SetItemString(dict, "__file__", pyfilename); Runtime.PyDict_SetItemString(dict, "__doc__", pydocstring); - Runtime.PyDict_SetItemString(dict, "__class__", pycls); + Runtime.PyDict_SetItemString(dict, "__class__", pycls.DangerousGetAddress()); Runtime.XDecref(pyname); Runtime.XDecref(pyfilename); Runtime.XDecref(pydocstring); diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 2d76f03b5..1037ad1c7 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -995,7 +995,8 @@ internal static bool PyObject_IsIterable(BorrowedReference pointer) internal static int PyObject_HasAttrString(IntPtr pointer, string name) => Delegates.PyObject_HasAttrString(pointer, name); - + internal static NewReference PyObject_GetAttrString(BorrowedReference pointer, string name) + => NewReference.DangerousFromPointer(PyObject_GetAttrString(pointer.DangerousGetAddress(), name)); internal static IntPtr PyObject_GetAttrString(IntPtr pointer, string name) => Delegates.PyObject_GetAttrString(pointer, name); @@ -1826,6 +1827,8 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) { return PyType_GenericAlloc(type, new IntPtr(n)); } + internal static NewReference PyType_GenericAlloc(BorrowedReference type, long n) + => NewReference.DangerousFromPointer(PyType_GenericAlloc(type.DangerousGetAddress(), n)); private static IntPtr PyType_GenericAlloc(IntPtr type, IntPtr n) => Delegates.PyType_GenericAlloc(type, n); @@ -1899,7 +1902,7 @@ internal static void PyErr_Fetch(out NewReference type, out NewReference 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); + internal static int PyCell_Set(BorrowedReference cell, BorrowedReference value) => Delegates.PyCell_Set(cell, value); //==================================================================== // Miscellaneous @@ -3340,7 +3343,7 @@ int updatepath internal static PyCell_SetDelegate PyCell_Set { get; } [global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] - internal delegate int PyCell_SetDelegate(BorrowedReference cell, IntPtr value); + internal delegate int PyCell_SetDelegate(BorrowedReference cell, BorrowedReference value); internal static PyMethod_SelfDelegate PyMethod_Self { get; } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 24b2cd8de..b2a1f9379 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -37,7 +37,7 @@ public static void Reset() /// object. These Python type instances are used to implement internal /// descriptor and utility types like ModuleObject, PropertyObject, etc. /// - internal static IntPtr GetTypeHandle(Type type) + internal static BorrowedReference GetTypeHandle(Type type) { // Note that these types are cached with a refcount of 1, so they // effectively exist until the CPython runtime is finalized. @@ -45,11 +45,11 @@ internal static IntPtr GetTypeHandle(Type type) cache.TryGetValue(type, out handle); if (handle != IntPtr.Zero) { - return handle; + return new BorrowedReference(handle); } handle = CreateType(type); cache[type] = handle; - return handle; + return new BorrowedReference(handle); } @@ -58,17 +58,17 @@ internal static IntPtr GetTypeHandle(Type type) /// The given ManagedType instance is a managed object that implements /// the appropriate semantics in Python for the reflected managed type. /// - internal static IntPtr GetTypeHandle(ManagedType obj, Type type) + internal static BorrowedReference GetTypeHandle(ManagedType obj, Type type) { IntPtr handle; cache.TryGetValue(type, out handle); if (handle != IntPtr.Zero) { - return handle; + return new BorrowedReference(handle); } handle = CreateType(obj, type); cache[type] = handle; - return handle; + return new BorrowedReference(handle); } @@ -298,7 +298,7 @@ static PyTuple GetBaseTypeTuple(Type clrType) return new PyTuple(bases); } - internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) + internal static BorrowedReference CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr py_dict) { // Utility to create a subtype of a managed type with the ability for the // a python subtype able to override the managed implementation @@ -350,7 +350,7 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr var baseClass = ManagedType.GetManagedObject(py_base_type) as ClassBase; if (null == baseClass) { - return Exceptions.RaiseTypeError("invalid base class, expected CLR class type"); + return new BorrowedReference(Exceptions.RaiseTypeError("invalid base class, expected CLR class type")); } try @@ -363,30 +363,32 @@ internal static IntPtr CreateSubType(IntPtr py_name, IntPtr py_base_type, IntPtr // create the new ManagedType and python type ClassBase subClass = ClassManager.GetClass(subType); - IntPtr py_type = GetTypeHandle(subClass, subType); - if (py_type == IntPtr.Zero) + BorrowedReference py_type = GetTypeHandle(subClass, subType); + if (py_type.IsNull) { - return IntPtr.Zero; + return new BorrowedReference(); } // 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); + IntPtr cls_dict = Marshal.ReadIntPtr(py_type.DangerousGetAddress(), TypeOffset.tp_dict); Runtime.PyDict_Update(cls_dict, py_dict); // Update the __classcell__ if it exists var cell = new BorrowedReference(Runtime.PyDict_GetItemString(cls_dict, "__classcell__")); if (!cell.IsNull) { - Runtime.PyCell_Set(cell, py_type); - Runtime.PyDict_DelItemString(cls_dict, "__classcell__"); + int r = Runtime.PyCell_Set(cell, py_type); + if (r == 0) return new BorrowedReference(); + r = Runtime.PyDict_DelItemString(cls_dict, "__classcell__"); + if (r == 0) return new BorrowedReference(); } return py_type; } catch (Exception e) { - return Exceptions.RaiseTypeError(e.Message); + return new BorrowedReference(Exceptions.RaiseTypeError(e.Message)); } } From e7ab3e7bd75f80ba529ed59bba36788159f0752a Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:48:41 -0700 Subject: [PATCH 202/240] added DebuggerDisplay to CLRObject --- src/runtime/clrobject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 04ba74862..058e042b1 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -1,8 +1,10 @@ using System; +using System.Diagnostics; using System.Runtime.InteropServices; namespace Python.Runtime { + [DebuggerDisplay("clrO: {inst}")] internal class CLRObject : ManagedType { internal object inst; From 7cd2bea26ea93ed5c7bf18e52e5ec390f9cb1584 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:49:29 -0700 Subject: [PATCH 203/240] a bit more tests for collection mixins --- src/embed_tests/CollectionsMixins.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/CollectionsMixins.cs b/src/embed_tests/CollectionsMixins.cs index 7ac0a5cfb..33bde1876 100644 --- a/src/embed_tests/CollectionsMixins.cs +++ b/src/embed_tests/CollectionsMixins.cs @@ -16,20 +16,32 @@ public void Enumerables_Iterable() { } [Test] public void Dict_Items_Iterable() { - var pyDict = this.dict.ToPython(); + var pyDict = MakeDict().ToPython(); var items = pyDict.InvokeMethod("items"); using var scope = Py.CreateScope(); scope.Set("iterator", this.Iter.Invoke(items)); scope.Set("s", ""); scope.Exec("for i in iterator: s += str(i)"); + scope.Get("s"); } - readonly Dictionary dict = new Dictionary { + [Test] + public void Dict() + { + var dict = MakeDict(); + var pyDict = dict.ToPython(); + Assert.IsTrue(pyDict.InvokeMethod("__contains__", "42".ToPython()).As()); + Assert.IsFalse(pyDict.InvokeMethod("__contains__", "21".ToPython()).As()); + Assert.AreEqual("12", pyDict.InvokeMethod("get", "21".ToPython(), "12".ToPython()).As()); + Assert.AreEqual(null, pyDict.InvokeMethod("get", "21".ToPython()).As()); + Assert.AreEqual("1", pyDict.InvokeMethod("pop", "10".ToPython(), "1".ToPython()).As()); + } + + static Dictionary MakeDict() => new Dictionary { ["42"] = new object(), [new object()] = "21", }; - readonly Lazy iter = new Lazy(() => PythonEngine.Eval("iter")); - PyObject Iter => this.iter.Value; + PyObject Iter => PythonEngine.Eval("iter"); [OneTimeSetUp] public void SetUp() { From 6b698410118a425de64c97a514fcc672e1dff857 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:50:11 -0700 Subject: [PATCH 204/240] simplified Dispatcher Dispose and finalizer --- src/runtime/delegatemanager.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 24783ae77..93e92dae5 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -185,11 +185,10 @@ public class Dispatcher : IPyDisposable { public IntPtr target; public Type dtype; - private bool _disposed = false; - private bool _finalized = false; public Dispatcher(IntPtr target, Type dtype) { + if (target == IntPtr.Zero) throw new ArgumentNullException(nameof(target)); Runtime.XIncref(target); this.target = target; this.dtype = dtype; @@ -197,21 +196,20 @@ public Dispatcher(IntPtr target, Type dtype) ~Dispatcher() { - if (_finalized || _disposed) + if (this.target == IntPtr.Zero) { return; } - _finalized = true; Finalizer.Instance.AddFinalizedObject(this); } public void Dispose() { - if (_disposed) + DebugUtil.EnsureGIL(); + if (this.target == IntPtr.Zero) { return; } - _disposed = true; Runtime.XDecref(target); target = IntPtr.Zero; dtype = null; From 3d2be524c55f2b8bac37666a8b06f3bd48be8460 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:50:46 -0700 Subject: [PATCH 205/240] TypeManager add incref for qualname --- src/runtime/typemanager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index b2a1f9379..5c6e5640c 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -508,7 +508,7 @@ internal static IntPtr AllocateTypeObject(string name, IntPtr typeType) IntPtr raw = Runtime.PyUnicode_AsUTF8(temp); Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); Marshal.WriteIntPtr(type, TypeOffset.name, temp); - + Runtime.XIncref(temp); Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); long ptr = type.ToInt64(); // 64-bit safe From cb4fd3ee917621252b2761e6a6a54a3dd6f59e8d Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:52:10 -0700 Subject: [PATCH 206/240] insignificant whitespace changes --- src/runtime/pythonengine.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 79acca0a3..2bffdb9d2 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -363,7 +363,7 @@ public static void Shutdown() if (initialized) { PyScopeManager.Global.Clear(); - + // If the shutdown handlers trigger a domain unload, // don't call shutdown again. AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload; @@ -631,7 +631,7 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, borrowedGlobals = false; } } - + if (locals == null) { locals = globals; @@ -694,7 +694,7 @@ public static PyScope CreateScope(string name) var scope = PyScopeManager.Global.Create(name); return scope; } - + public class GILState : IDisposable { private readonly IntPtr state; @@ -795,7 +795,7 @@ public static void SetArgv(IEnumerable argv) public static void With(PyObject obj, Action Body) { - // Behavior described here: + // Behavior described here: // https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers IntPtr type = Runtime.PyNone; From cf8d97b08dc9ba2904c6444749e1c933c8a95e09 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 13:57:01 -0700 Subject: [PATCH 207/240] use lifetime-typed references in argument type conversion in MethodBinder --- src/runtime/converter.cs | 15 ++++++++++++++- src/runtime/methodbinder.cs | 17 +++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 2f4c0aad8..59156c694 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -50,6 +50,11 @@ static Converter() } + /// + /// Given a builtin Python type, return the corresponding CLR type. + /// + internal static Type GetTypeByAlias(BorrowedReference type) + => GetTypeByAlias(type.DangerousGetAddress()); /// /// Given a builtin Python type, return the corresponding CLR type. /// @@ -76,7 +81,9 @@ internal static Type GetTypeByAlias(IntPtr op) return null; } - internal static IntPtr GetPythonTypeByAlias(Type op) + internal static BorrowedReference GetPythonTypeByAlias(Type type) + => new BorrowedReference(GetPythonTypeByAliasUnsafe(type)); + static IntPtr GetPythonTypeByAliasUnsafe(Type op) { if (op == stringType) return Runtime.PyUnicodeType; @@ -246,6 +253,12 @@ internal static IntPtr ToPythonImplicit(object value) } + /// + /// Return a managed object for the given Python object, taking funny + /// byref types into account. + /// + internal static bool ToManaged(BorrowedReference value, Type type, out object result, bool setError) + => ToManaged(value.DangerousGetAddress(), type: type, out result, setError: setError); /// /// Return a managed object for the given Python object, taking funny /// byref types into account. diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 15f50478d..84a66ed32 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -460,7 +460,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, } bool isOut; - if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { + if (!TryConvertArgument(new BorrowedReference(op), parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut)) { return null; } @@ -481,7 +481,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray, return margs; } - static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution, + static bool TryConvertArgument(BorrowedReference op, Type parameterType, bool needsResolution, out object arg, out bool isOut) { arg = null; @@ -502,31 +502,29 @@ static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResoluti return true; } - static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool needsResolution) + static Type TryComputeClrArgumentType(Type parameterType, BorrowedReference argument, bool needsResolution) { // this logic below handles cases when multiple overloading methods // are ambiguous, hence comparison between Python and CLR types // is necessary Type clrtype = null; - IntPtr pyoptype; if (needsResolution) { // HACK: each overload should be weighted in some way instead - pyoptype = Runtime.PyObject_Type(argument); + BorrowedReference pyoptype = Runtime.PyObject_TYPE(argument); Exceptions.Clear(); - if (pyoptype != IntPtr.Zero) + if (!pyoptype.IsNull) { clrtype = Converter.GetTypeByAlias(pyoptype); } - Runtime.XDecref(pyoptype); } if (clrtype != null) { if ((parameterType != typeof(object)) && (parameterType != clrtype)) { - IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType); - pyoptype = Runtime.PyObject_Type(argument); + BorrowedReference pytype = Converter.GetPythonTypeByAlias(parameterType); + BorrowedReference pyoptype = Runtime.PyObject_TYPE(argument); Exceptions.Clear(); bool typematch = false; @@ -546,7 +544,6 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument, bool clrtype = parameterType; } } - Runtime.XDecref(pyoptype); if (!typematch) { return null; From 6deab924645d71e1a039bcddf37c45f3f549ed16 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 14:07:16 -0700 Subject: [PATCH 208/240] added a few error checks --- src/runtime/pyobject.cs | 2 ++ src/runtime/runtime.cs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index d67e6a89e..85e30cdad 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -165,6 +165,8 @@ public object AsManagedObject(Type t) /// protected virtual void Dispose(bool disposing) { + DebugUtil.EnsureGIL(); + if (this.obj == IntPtr.Zero) { return; diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 1037ad1c7..3234e1090 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1536,9 +1536,10 @@ internal static string GetManagedString(IntPtr op) if (type == PyUnicodeType) { IntPtr p = PyUnicode_AsUnicode(op); - int length = (int)PyUnicode_GetSize(op); + Exceptions.ErrorCheck(p); + int length = checked((int)PyUnicode_GetSize(op)); - int size = length * UCS; + int size = checked(length * UCS); var buffer = new byte[size]; Marshal.Copy(p, buffer, 0, size); return PyEncoding.GetString(buffer, 0, size); From 1360fc89052856e99e61e44fcc6564bdcca0f821 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 14:15:11 -0700 Subject: [PATCH 209/240] use PyType_FastSubclass for some type checks --- src/embed_tests/TestRuntime.cs | 18 ++++++++++++++++++ src/runtime/classbase.cs | 2 +- src/runtime/classderived.cs | 2 +- src/runtime/interop.cs | 21 +++++++++++++++------ src/runtime/moduleobject.cs | 2 +- src/runtime/pytype.cs | 4 ++-- src/runtime/runtime.cs | 15 ++++++++++++--- 7 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs index 2dd308f9e..2c268cf73 100644 --- a/src/embed_tests/TestRuntime.cs +++ b/src/embed_tests/TestRuntime.cs @@ -130,5 +130,23 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test() Runtime.Runtime.Py_Finalize(); } + + [Test] + public static void PyType_Check_Sanity() + { + Runtime.Runtime.Py_Initialize(); + var builtins = Runtime.Runtime.GetBuiltins(); + var obj = Runtime.Runtime.PyObject_GetAttrString(builtins, "object"); + var t = Runtime.Runtime.PyObject_GetAttrString(builtins, "True"); + var none = Runtime.Runtime.PyObject_GetAttrString(builtins, "None"); + var noneType = Runtime.Runtime.PyObject_TYPE(none); + var type = Runtime.Runtime.PyObject_TYPE(noneType); + + Assert.IsTrue(Runtime.Runtime.PyType_Check(new BorrowedReference(obj))); + Assert.IsTrue(Runtime.Runtime.PyType_Check(new BorrowedReference(type))); + Assert.IsFalse(Runtime.Runtime.PyType_Check(new BorrowedReference(t))); + + Runtime.Runtime.Py_Finalize(); + } } } diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs index 115dc097f..3e11b3d3e 100644 --- a/src/runtime/classbase.cs +++ b/src/runtime/classbase.cs @@ -293,7 +293,7 @@ public static void tp_dealloc(IntPtr ob) { var reference = new BorrowedReference(ob); var self = GetManagedObject(reference, ObjectOffset.ReflectedObjectGCHandle(reference)); - IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.TypeDictOffset(self.tpHandle)); + IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.TypeDictOffset(self.Type)); if (dict != IntPtr.Zero) { Runtime.XDecref(dict); diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index b6f0a2581..2cb874ce4 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -877,7 +877,7 @@ public static void Finalize(IPythonDerivedType obj) // the C# object is being destroyed which must mean there are no more // references to the Python object as well so now we can dealloc the // python object. - IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.TypeDictOffset(self.tpHandle)); + IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.TypeDictOffset(self.Type)); if (dict != IntPtr.Zero) { Runtime.XDecref(dict); diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 0b1347d42..5ed8d91d0 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -111,24 +111,33 @@ internal static void ClrGcHandleOffsetAssertSanity(int offset) /// /// Returns dict offset in instances of the specified /// - public static int TypeDictOffset(BorrowedReference type) - => TypeDictOffset(type.DangerousGetAddress()); - public static int TypeDictOffset(IntPtr type) { - Debug.Assert(Runtime.PyType_Check(type)); - return Runtime.PyType_IsSubtype(type, Exceptions.BaseException) + public static int TypeDictOffset(BorrowedReference type) { + if (!Runtime.PyType_Check(type)) + throw new ArgumentException("Bad object type"); + + return IsExceptionSubtype(type) ? ExceptionOffset.ob_dict : ob_dict; } + public static int TypeDictOffset(IntPtr type) + => TypeDictOffset(new BorrowedReference(type)); public static int Size(IntPtr ob) { if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || - (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) { + (Runtime.PyType_Check(new BorrowedReference(ob)) && IsExceptionSubtype(new BorrowedReference(ob))))) { return ExceptionOffset.Size(); } return PyObject_HEAD_Size(); } + static bool IsExceptionSubtype(BorrowedReference type) + { + bool isException = Runtime.PyType_FastSubclass(type, TypeFlags.BaseExceptionSubclass); + Debug.Assert(Runtime.PyType_IsSubtype(type.DangerousGetAddress(), Exceptions.BaseException) == isException); + return isException; + } + public static int PyObject_HEAD_Size() { #if PYTHON_WITH_PYDEBUG return 6 * IntPtr.Size; diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index f3efbb2a9..abab4f8b2 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -54,7 +54,7 @@ public ModuleObject(string name) Runtime.XDecref(pyfilename); Runtime.XDecref(pydocstring); - Marshal.WriteIntPtr(pyHandle, ObjectOffset.TypeDictOffset(tpHandle), dict); + Marshal.WriteIntPtr(pyHandle, ObjectOffset.TypeDictOffset(Type), dict); InitializeModuleMembers(); } diff --git a/src/runtime/pytype.cs b/src/runtime/pytype.cs index 1bf26e38a..14d394360 100644 --- a/src/runtime/pytype.cs +++ b/src/runtime/pytype.cs @@ -34,7 +34,7 @@ public static bool IsTypeType(PyObject obj) { throw new ArgumentNullException(nameof(obj)); } - return Runtime.PyType_Check(obj.Handle); + return Runtime.PyType_Check(obj.Reference); } /// @@ -45,7 +45,7 @@ public static bool IsTypeType(IntPtr typeHandle) { throw new ArgumentNullException(nameof(typeHandle)); } - return Runtime.PyType_Check(typeHandle); + return Runtime.PyType_Check(new BorrowedReference(typeHandle)); } /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 3234e1090..835053b90 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -595,7 +595,7 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) for (var i = 0; i < n; i++) { - IntPtr op = PyTuple_GetItem(args, i); + var op = new BorrowedReference(PyTuple_GetItem(args, i)); if (mangleObjects && (!PyType_Check(op))) { op = PyObject_TYPE(op); @@ -1802,9 +1802,18 @@ int updatepath // Python type object API //==================================================================== - internal static bool PyType_Check(IntPtr ob) + internal static bool PyType_Check(BorrowedReference ob) { - return PyObject_TypeCheck(ob, PyTypeType); + // fast path using raw memory access + BorrowedReference type = PyObject_TYPE(ob); + if (type == PyTypeType) return true; + return PyType_FastSubclass(type, TypeFlags.TypeSubclass); + } + + internal static bool PyType_FastSubclass(BorrowedReference type, TypeFlags baseType) + { + var flags = (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags); + return (flags & baseType) != 0; } internal static void PyType_Modified(IntPtr type) => Delegates.PyType_Modified(type); From 1a6f2fca0bb92d00724f2b3b835f7a4f0c9e70af Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Wed, 17 Jun 2020 14:23:14 -0700 Subject: [PATCH 210/240] remove unused PyUnicodeEntryPoint --- src/runtime/runtime.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 835053b90..7a17d2ff7 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -51,7 +51,6 @@ static Runtime() { // binary substitution of different Python.Runtime.dll builds in a target application. public static int UCS { get; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 4; - public static string PyUnicodeEntryPoint { get; } = UCS == 2 ? "PyUnicodeUCS2_" : "PyUnicodeUCS4_"; // C# compiler copies constants to the assemblies that references this library. // We needs to replace all public constants to static readonly fields to allow From 77c60932f4cefd1e30059027f4e1cce2157a4f0c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 25 Jun 2020 18:00:54 -0700 Subject: [PATCH 211/240] removed obsoletion of TupleCodec and RawProxyEncoder --- src/runtime/Codecs/RawProxyEncoder.cs | 1 - src/runtime/Codecs/TupleCodecs.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/runtime/Codecs/RawProxyEncoder.cs b/src/runtime/Codecs/RawProxyEncoder.cs index a1b6c52b3..37ad0487b 100644 --- a/src/runtime/Codecs/RawProxyEncoder.cs +++ b/src/runtime/Codecs/RawProxyEncoder.cs @@ -6,7 +6,6 @@ namespace Python.Runtime.Codecs /// A .NET object encoder, that returns raw proxies (e.g. no conversion to Python types). /// You must inherit from this class and override . /// - [Obsolete(Util.UnstableApiMessage)] public class RawProxyEncoder: IPyObjectEncoder { public PyObject TryEncode(object value) diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs index 4fa79e04c..44c5dc5a4 100644 --- a/src/runtime/Codecs/TupleCodecs.cs +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -5,7 +5,6 @@ namespace Python.Runtime.Codecs using System.Linq; using System.Reflection; - [Obsolete(Util.UnstableApiMessage)] public sealed class TupleCodec : IPyObjectEncoder, IPyObjectDecoder { TupleCodec() { } From cccdce587b05e2c69243deab3aa64eff7d0ded52 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 25 Jun 2020 18:02:52 -0700 Subject: [PATCH 212/240] updated license for release --- LICENSE | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index 0d2045bdd..788160102 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,5 @@ -This software is "code-available" to assist with Gradient debugging. -You must have a license for the matching version of Gradient (see -https://github.com/losttech/Gradient/) to access this source. Only -Gradient debugging is permitted. +You must have a license for LostTech.TensorFlow +(see https://losttech.software/gradient.html) to use this software. If you wish to obtain a version of this sofware with a more liberal license, refer to https://github.com/pythonnet/pythonnet. From dd0229c4eb41fe57f7b5f17831dc9d0fdaefd941 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 25 Jun 2020 18:03:11 -0700 Subject: [PATCH 213/240] include license into the NuGet package --- src/runtime/Python.Runtime.15.csproj | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 520ebda6f..c12db4565 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,11 +1,12 @@ - + netstandard2.0;net40 AnyCPU Python.Runtime Python.Runtime LostTech.Python.Runtime - https://raw.githubusercontent.com/losttech/Gradient/master/LICENSE-TECH-PREVIEW.txt + LICENSE + true This software is part of Gradient: https://losttech.software/gradient.html 3.0.0 true @@ -59,6 +60,10 @@ + + + + clr.py From bc2e9aade44326e35828c329ed35ae435e5c8046 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 25 Jun 2020 18:33:10 -0700 Subject: [PATCH 214/240] enabled source link --- src/runtime/Python.Runtime.15.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index c12db4565..eaeb8dc48 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -7,6 +7,7 @@ LostTech.Python.Runtime LICENSE true + true This software is part of Gradient: https://losttech.software/gradient.html 3.0.0 true @@ -88,6 +89,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + From 8299148d8b4dbed5be3ba2ccfd661710b7c8d564 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Thu, 25 Jun 2020 18:33:32 -0700 Subject: [PATCH 215/240] updated assembly info --- pythonnet.15.sln | 1 + src/SharedAssemblyInfo.cs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pythonnet.15.sln b/pythonnet.15.sln index d561438c6..82b70fb09 100644 --- a/pythonnet.15.sln +++ b/pythonnet.15.sln @@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{441A0123-F CHANGELOG.md = CHANGELOG.md LICENSE = LICENSE README.rst = README.rst + src\SharedAssemblyInfo.cs = src\SharedAssemblyInfo.cs EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI", "CI", "{D301657F-5EAF-4534-B280-B858D651B2E5}" diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index dd057b144..071360e55 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -7,9 +7,9 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("pythonnet")] -[assembly: AssemblyProduct("Python.NET")] -[assembly: AssemblyCopyright("Copyright (c) 2006-2020 the contributors of the Python.NET project")] +[assembly: AssemblyCompany("Lost Tech LLC")] +[assembly: AssemblyProduct("LostTech.Python.Runtime")] +[assembly: AssemblyCopyright("Copyright (c) 2006-2020 Lost Tech and the contributors of the Python.NET project")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -25,4 +25,4 @@ // Version Information. Keeping it simple. May need to revisit for Nuget // See: https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/ // AssemblyVersion can only be numeric -[assembly: AssemblyVersion("2.5.0")] +[assembly: AssemblyVersion("3.0.0")] From 1f63b016467e0169aae8120b1bb6878b1a63f389 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 27 Jun 2020 13:34:55 -0700 Subject: [PATCH 216/240] bumped version to 3.0.1 --- src/runtime/Python.Runtime.15.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index eaeb8dc48..033372a60 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net40 AnyCPU @@ -9,7 +9,7 @@ true true This software is part of Gradient: https://losttech.software/gradient.html - 3.0.0 + 3.0.1 true true snupkg From 77b0145a762068e3f4c6f11b659253b4f056da02 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 27 Jun 2020 14:34:28 -0700 Subject: [PATCH 217/240] fixed a bug, that caused out parameters not to be affected by codecs --- src/embed_tests/Codecs.cs | 16 ++++++++++++++++ src/runtime/converter.cs | 4 ++-- src/runtime/methodbinder.cs | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/embed_tests/Codecs.cs b/src/embed_tests/Codecs.cs index ac986c9f0..aa7627847 100644 --- a/src/embed_tests/Codecs.cs +++ b/src/embed_tests/Codecs.cs @@ -151,6 +151,22 @@ public void ExceptionStringValue() { StringAssert.Contains("blah", error.Message); } + [Test] + public void OutParameterEncoded() + { + var enumEncoder = new FakeEncoder(); + RegisterEncoder(enumEncoder); + + using var scope = Py.CreateScope(); + scope.Set("func", new Codecs().ToPython().GetAttr(nameof(GetModifiers))); + scope.Set("dummy", PyObject.FromManagedObject(ConsoleModifiers.Shift)); + var evalResult = scope.Eval("func(dummy)").As(); + Assert.AreSame(enumEncoder, evalResult); + Assert.AreEqual(ConsoleModifiers.Control, enumEncoder.LastObject); + } + + public void GetModifiers(out ConsoleModifiers result) => result = ConsoleModifiers.Control; + class ValueErrorWrapper : Exception { public ValueErrorWrapper(string message) : base(message) { } } diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 59156c694..0e558b3be 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -2,11 +2,10 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; -using System.Reflection; using System.Runtime.InteropServices; using System.Security; -using System.ComponentModel; namespace Python.Runtime { @@ -123,6 +122,7 @@ internal static IntPtr ToPython(T value) internal static IntPtr ToPython(object value, Type type) { + Debug.Assert(type is null || !type.IsByRef); if (value is PyObject pyObject) { IntPtr handle = pyObject.Handle; diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 84a66ed32..b08068325 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -745,7 +745,7 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i Type pt = pi[i].ParameterType; if (pi[i].IsOut || pt.IsByRef) { - v = Converter.ToPython(binding.args[i], pt); + v = Converter.ToPython(binding.args[i], pt.GetElementType()); Runtime.PyTuple_SetItem(t, n, v); n++; } From d2da724e1b58bb6d6a526a1aaf8c8ae5d20c30ef Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Tue, 7 Jul 2020 19:19:33 -0700 Subject: [PATCH 218/240] when converting to Python, always use actual value type --- src/runtime/Codecs/TupleCodecs.cs | 2 +- src/runtime/arrayobject.cs | 4 ++-- src/runtime/classderived.cs | 8 +++---- src/runtime/converter.cs | 35 +++---------------------------- src/runtime/delegatemanager.cs | 2 +- src/runtime/fieldobject.cs | 4 ++-- src/runtime/indexer.cs | 2 +- src/runtime/iterator.cs | 2 +- src/runtime/methodbinder.cs | 6 +++--- src/runtime/propertyobject.cs | 4 ++-- src/runtime/pyobject.cs | 4 ++-- src/runtime/pyscope.cs | 2 +- src/runtime/pythonengine.cs | 2 +- src/runtime/typemanager.cs | 4 ++-- 14 files changed, 26 insertions(+), 55 deletions(-) diff --git a/src/runtime/Codecs/TupleCodecs.cs b/src/runtime/Codecs/TupleCodecs.cs index 44c5dc5a4..0ed0f6674 100644 --- a/src/runtime/Codecs/TupleCodecs.cs +++ b/src/runtime/Codecs/TupleCodecs.cs @@ -34,7 +34,7 @@ public PyObject TryEncode(object value) foreach (FieldInfo field in tupleType.GetFields()) { var item = field.GetValue(value); - IntPtr pyItem = Converter.ToPython(item, item?.GetType() ?? field.FieldType); + IntPtr pyItem = Converter.ToPython(item); Runtime.PyTuple_SetItem(tuple, fieldIndex, pyItem); fieldIndex++; } diff --git a/src/runtime/arrayobject.cs b/src/runtime/arrayobject.cs index e489fbcff..42a394cad 100644 --- a/src/runtime/arrayobject.cs +++ b/src/runtime/arrayobject.cs @@ -84,7 +84,7 @@ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) return IntPtr.Zero; } - return Converter.ToPython(value, itemType); + return Converter.ToPython(value); } // Multi-dimensional arrays can be indexed a la: list[1, 2, 3]. @@ -127,7 +127,7 @@ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) return IntPtr.Zero; } - return Converter.ToPython(value, itemType); + return Converter.ToPython(value); } diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index 2cb874ce4..fc81591b9 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -59,7 +59,7 @@ internal ClassDerivedObject(Type tp) : base(tp) // return the pointer to the python object // (this indirectly calls ClassDerivedObject.ToPython) - return Converter.ToPython(obj, cls.GetType()); + return Converter.ToPython(obj); } public new static void tp_dealloc(IntPtr ob) @@ -660,7 +660,7 @@ public static T InvokeMethod(IPythonDerivedType obj, string methodName, strin var pyargs = new PyObject[args.Length]; for (var i = 0; i < args.Length; ++i) { - pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i])); + pyargs[i] = new PyObject(Converter.ToPython(args[i])); disposeList.Add(pyargs[i]); } @@ -722,7 +722,7 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s var pyargs = new PyObject[args.Length]; for (var i = 0; i < args.Length; ++i) { - pyargs[i] = new PyObject(Converter.ToPythonImplicit(args[i])); + pyargs[i] = new PyObject(Converter.ToPython(args[i])); disposeList.Add(pyargs[i]); } @@ -795,7 +795,7 @@ public static void InvokeSetProperty(IPythonDerivedType obj, string propertyN { Runtime.XIncref(self.pyHandle); using (var pyself = new PyObject(self.pyHandle)) - using (var pyvalue = new PyObject(Converter.ToPythonImplicit(value))) + using (var pyvalue = new PyObject(Converter.ToPython(value))) { pyself.SetAttr(propertyName, pyvalue); } diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 0e558b3be..68dce2597 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -108,21 +108,14 @@ static IntPtr GetPythonTypeByAliasUnsafe(Type op) return IntPtr.Zero; } - /// /// Return a Python object for the given native object, converting /// basic types (string, int, etc.) into equivalent Python objects. /// This always returns a new reference. Note that the System.Decimal /// type has no Python equivalent and converts to a managed instance. /// - internal static IntPtr ToPython(T value) + internal static IntPtr ToPython(object? value) { - return ToPython(value, typeof(T)); - } - - internal static IntPtr ToPython(object value, Type type) - { - Debug.Assert(type is null || !type.IsByRef); if (value is PyObject pyObject) { IntPtr handle = pyObject.Handle; @@ -141,6 +134,7 @@ internal static IntPtr ToPython(object value, Type type) return result; } + var type = value.GetType(); if (EncodersAllowed(type)) { var encoded = PyObjectConversions.TryEncode(value, type); if (encoded != null) { @@ -166,12 +160,6 @@ internal static IntPtr ToPython(object value, Type type) #endif } - // hmm - from Python, we almost never care what the declared - // type is. we'd rather have the object bound to the actual - // implementing class. - - type = value.GetType(); - TypeCode tc = Type.GetTypeCode(type); switch (tc) @@ -236,23 +224,6 @@ internal static IntPtr ToPython(object value, Type type) } - /// - /// In a few situations, we don't have any advisory type information - /// when we want to convert an object to Python. - /// - internal static IntPtr ToPythonImplicit(object value) - { - if (value == null) - { - IntPtr result = Runtime.PyNone; - Runtime.XIncref(result); - return result; - } - - return ToPython(value, objectType); - } - - /// /// Return a managed object for the given Python object, taking funny /// byref types into account. @@ -872,7 +843,7 @@ public static class ConverterExtension { public static PyObject ToPython(this object o) { - return new PyObject(Converter.ToPython(o, o?.GetType())); + return new PyObject(Converter.ToPython(o)); } } } diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 93e92dae5..7e518bfcf 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -241,7 +241,7 @@ public object TrueDispatch(ArrayList args) { // Here we own the reference to the Python value, and we // give the ownership to the arg tuple. - IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType); + IntPtr arg = Converter.ToPython(args[i]); Runtime.PyTuple_SetItem(pyargs, i, arg); } diff --git a/src/runtime/fieldobject.cs b/src/runtime/fieldobject.cs index 7c9a466d5..d0b854c82 100644 --- a/src/runtime/fieldobject.cs +++ b/src/runtime/fieldobject.cs @@ -43,7 +43,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) try { result = info.GetValue(null); - return Converter.ToPython(result, info.FieldType); + return Converter.ToPython(result); } catch (Exception e) { @@ -56,7 +56,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { var co = (CLRObject)GetManagedObject(ob); result = info.GetValue(co.inst); - return Converter.ToPython(result, info.FieldType); + return Converter.ToPython(result); } catch (Exception e) { diff --git a/src/runtime/indexer.cs b/src/runtime/indexer.cs index 71f7e7aa1..26e028172 100644 --- a/src/runtime/indexer.cs +++ b/src/runtime/indexer.cs @@ -109,7 +109,7 @@ internal IntPtr GetDefaultArgs(IntPtr args) { continue; } - IntPtr arg = Converter.ToPython(pi[i + pynargs].DefaultValue, pi[i + pynargs].ParameterType); + IntPtr arg = Converter.ToPython(pi[i + pynargs].DefaultValue); Runtime.PyTuple_SetItem(defaultArgs, i, arg); } return defaultArgs; diff --git a/src/runtime/iterator.cs b/src/runtime/iterator.cs index d380f20ad..93246fdd4 100644 --- a/src/runtime/iterator.cs +++ b/src/runtime/iterator.cs @@ -37,7 +37,7 @@ public static IntPtr tp_iternext(IntPtr ob) return IntPtr.Zero; } object item = self.iter.Current; - return Converter.ToPythonImplicit(item); + return Converter.ToPython(item); } public static IntPtr tp_iter(IntPtr ob) diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index b08068325..4dcc088d9 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -736,7 +736,7 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i var n = 0; IntPtr t = Runtime.PyTuple_New(binding.outs + 1); - IntPtr v = Converter.ToPython(result, mi.ReturnType); + IntPtr v = Converter.ToPython(result); Runtime.PyTuple_SetItem(t, n, v); n++; @@ -745,7 +745,7 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i Type pt = pi[i].ParameterType; if (pi[i].IsOut || pt.IsByRef) { - v = Converter.ToPython(binding.args[i], pt.GetElementType()); + v = Converter.ToPython(binding.args[i]); Runtime.PyTuple_SetItem(t, n, v); n++; } @@ -762,7 +762,7 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i return t; } - return Converter.ToPython(result, mi.ReturnType); + return Converter.ToPython(result); } } diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index ae8dca15b..0cb6e85bf 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -52,7 +52,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) try { result = self.info.GetValue(null, null); - return Converter.ToPython(result, self.info.PropertyType); + return Converter.ToPython(result); } catch (Exception e) { @@ -69,7 +69,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) try { result = self.info.GetValue(co.inst, null); - return Converter.ToPython(result, self.info.PropertyType); + return Converter.ToPython(result); } catch (Exception e) { diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 85e30cdad..d19765111 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -1161,7 +1161,7 @@ public override bool TryGetMember(GetMemberBinder binder, out object result) public override bool TrySetMember(SetMemberBinder binder, object value) { DebugUtil.EnsureGIL(); - IntPtr ptr = Converter.ToPython(value, value?.GetType()); + IntPtr ptr = Converter.ToPython(value); int r = Runtime.PyObject_SetAttrString(obj, binder.Name, ptr); if (r < 0) { @@ -1254,7 +1254,7 @@ private static IntPtr GetPythonObject(object target) } else { - ptr = Converter.ToPython(target, target?.GetType()); + ptr = Converter.ToPython(target); } return ptr; diff --git a/src/runtime/pyscope.cs b/src/runtime/pyscope.cs index 1a1e296ec..f9c4b19f7 100644 --- a/src/runtime/pyscope.cs +++ b/src/runtime/pyscope.cs @@ -370,7 +370,7 @@ public void Set(string name, object value) { this.EnsureNotDisposed(); - IntPtr _value = Converter.ToPython(value, value?.GetType()); + IntPtr _value = Converter.ToPython(value); try { this.SetInternal(name, new BorrowedReference(_value)); diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index 2bffdb9d2..ddbb5e38c 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -740,7 +740,7 @@ public static KeywordArguments kw(params object[] kv) } else { - value = Converter.ToPython(kv[i + 1], kv[i + 1]?.GetType()); + value = Converter.ToPython(kv[i + 1]); } if (Runtime.PyDict_SetItemString(dict.Handle, (string)kv[i], value) != 0) { diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 5c6e5640c..8214cc214 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -312,7 +312,7 @@ internal static BorrowedReference CreateSubType(IntPtr py_name, IntPtr py_base_t var disposeList = new List(); try { - var assemblyKey = new PyObject(Converter.ToPython("__assembly__", typeof(string))); + var assemblyKey = new PyObject(Converter.ToPython("__assembly__")); disposeList.Add(assemblyKey); if (0 != Runtime.PyMapping_HasKey(py_dict, assemblyKey.Handle)) { @@ -325,7 +325,7 @@ internal static BorrowedReference CreateSubType(IntPtr py_name, IntPtr py_base_t } } - var namespaceKey = new PyObject(Converter.ToPythonImplicit("__namespace__")); + var namespaceKey = new PyObject(Converter.ToPython("__namespace__")); disposeList.Add(namespaceKey); if (0 != Runtime.PyMapping_HasKey(py_dict, namespaceKey.Handle)) { From 394b308b771cfbdf616c19de91f10ae6d948ff1c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 4 Sep 2020 13:04:09 -0700 Subject: [PATCH 219/240] bumped version to 3.0.2 --- src/runtime/Python.Runtime.15.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 033372a60..877e55a31 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -9,7 +9,7 @@ true true This software is part of Gradient: https://losttech.software/gradient.html - 3.0.1 + 3.0.2 true true snupkg From 8e70b5bc5f912ad664a4bbc18b614b7c6bb4d500 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 4 Sep 2020 13:15:05 -0700 Subject: [PATCH 220/240] removed old project files --- pythonnet.sln | 202 -------------------- src/clrmodule/clrmodule.csproj | 95 --------- src/console/Console.csproj | 101 ---------- src/embed_tests/Python.EmbeddingTest.csproj | 143 -------------- src/runtime/Python.Runtime.csproj | 188 ------------------ src/testing/Python.Test.csproj | 117 ------------ 6 files changed, 846 deletions(-) delete mode 100644 pythonnet.sln delete mode 100644 src/clrmodule/clrmodule.csproj delete mode 100644 src/console/Console.csproj delete mode 100644 src/embed_tests/Python.EmbeddingTest.csproj delete mode 100644 src/runtime/Python.Runtime.csproj delete mode 100644 src/testing/Python.Test.csproj diff --git a/pythonnet.sln b/pythonnet.sln deleted file mode 100644 index c5afd66c3..000000000 --- a/pythonnet.sln +++ /dev/null @@ -1,202 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Runtime", "src\runtime\Python.Runtime.csproj", "{097B4AC0-74E9-4C58-BCF8-C69746EC8271}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Test", "src\testing\Python.Test.csproj", "{6F401A34-273B-450F-9A4C-13550BE0767B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.EmbeddingTest", "src\embed_tests\Python.EmbeddingTest.csproj", "{4165C59D-2822-499F-A6DB-EACA4C331EB5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "src\console\Console.csproj", "{E29DCF0A-5114-4A98-B1DD-71264B6EA349}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "clrmodule", "src\clrmodule\clrmodule.csproj", "{86E834DE-1139-4511-96CC-69636A56E7AC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - DebugMono|x64 = DebugMono|x64 - DebugMono|x86 = DebugMono|x86 - DebugMonoPY3|x64 = DebugMonoPY3|x64 - DebugMonoPY3|x86 = DebugMonoPY3|x86 - DebugWin|x64 = DebugWin|x64 - DebugWin|x86 = DebugWin|x86 - DebugWinPY3|x64 = DebugWinPY3|x64 - DebugWinPY3|x86 = DebugWinPY3|x86 - ReleaseMono|x64 = ReleaseMono|x64 - ReleaseMono|x86 = ReleaseMono|x86 - ReleaseMonoPY3|x64 = ReleaseMonoPY3|x64 - ReleaseMonoPY3|x86 = ReleaseMonoPY3|x86 - ReleaseWin|x64 = ReleaseWin|x64 - ReleaseWin|x86 = ReleaseWin|x86 - ReleaseWinPY3|x64 = ReleaseWinPY3|x64 - ReleaseWinPY3|x86 = ReleaseWinPY3|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMono|x64.Build.0 = DebugMono|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMono|x86.Build.0 = DebugMono|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWin|x64.Build.0 = DebugWin|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWin|x86.Build.0 = DebugWin|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMono|x64.Build.0 = DebugMono|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMono|x86.Build.0 = DebugMono|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWin|x64.Build.0 = DebugWin|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWin|x86.Build.0 = DebugWin|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {6F401A34-273B-450F-9A4C-13550BE0767B}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMono|x64.Build.0 = DebugMono|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMono|x86.Build.0 = DebugMono|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWin|x64.Build.0 = DebugWin|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWin|x86.Build.0 = DebugWin|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMono|x64.Build.0 = DebugMono|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMono|x86.Build.0 = DebugMono|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMonoPY3|x64.Build.0 = DebugMonoPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugMonoPY3|x86.Build.0 = DebugMonoPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWin|x64.Build.0 = DebugWin|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWin|x86.Build.0 = DebugWin|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMono|x64.Build.0 = ReleaseMono|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMono|x86.Build.0 = ReleaseMono|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMonoPY3|x64.Build.0 = ReleaseMonoPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseMonoPY3|x86.Build.0 = ReleaseMonoPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMono|x64.ActiveCfg = DebugMono|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMono|x86.ActiveCfg = DebugMono|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMonoPY3|x64.ActiveCfg = DebugMonoPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMonoPY3|x86.ActiveCfg = DebugMonoPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x64.Build.0 = DebugWin|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x86.Build.0 = DebugWin|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWinPY3|x64.ActiveCfg = DebugWinPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWinPY3|x64.Build.0 = DebugWinPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWinPY3|x86.ActiveCfg = DebugWinPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWinPY3|x86.Build.0 = DebugWinPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMono|x64.ActiveCfg = ReleaseMono|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMono|x86.ActiveCfg = ReleaseMono|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMonoPY3|x64.ActiveCfg = ReleaseMonoPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMonoPY3|x86.ActiveCfg = ReleaseMonoPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWinPY3|x64.ActiveCfg = ReleaseWinPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWinPY3|x64.Build.0 = ReleaseWinPY3|x64 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWinPY3|x86.ActiveCfg = ReleaseWinPY3|x86 - {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWinPY3|x86.Build.0 = ReleaseWinPY3|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = src\console\Console.csproj - Policies = $0 - $0.VersionControlPolicy = $1 - $1.inheritsSet = Mono - $0.ChangeLogPolicy = $2 - $2.UpdateMode = None - $2.MessageStyle = $3 - $3.LineAlign = 0 - $2.inheritsSet = Mono - EndGlobalSection -EndGlobal diff --git a/src/clrmodule/clrmodule.csproj b/src/clrmodule/clrmodule.csproj deleted file mode 100644 index 6e5ff4966..000000000 --- a/src/clrmodule/clrmodule.csproj +++ /dev/null @@ -1,95 +0,0 @@ - - - - Debug - AnyCPU - {86E834DE-1139-4511-96CC-69636A56E7AC} - Library - clrmodule - clrmodule - bin\clrmodule.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 6 - true - prompt - - - x86 - - - x64 - - - true - PYTHON2;TRACE;DEBUG - full - - - PYTHON2 - true - pdbonly - - - true - PYTHON2;TRACE;DEBUG - full - - - PYTHON2 - true - pdbonly - - - true - PYTHON3;TRACE;DEBUG - full - - - PYTHON3 - true - pdbonly - - - true - PYTHON3;TRACE;DEBUG - full - - - PYTHON3 - true - pdbonly - - - - ..\..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll - False - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - diff --git a/src/console/Console.csproj b/src/console/Console.csproj deleted file mode 100644 index ea88b6356..000000000 --- a/src/console/Console.csproj +++ /dev/null @@ -1,101 +0,0 @@ - - - - Debug - AnyCPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349} - Exe - nPython - Python.Runtime - bin\nPython.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 6 - python-clear.ico - prompt - - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - $(PythonManifest) - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - Python.Runtime.dll - - - - - {097b4ac0-74e9-4c58-bcf8-c69746ec8271} - Python.Runtime - - - - - - - diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj deleted file mode 100644 index 94c8dca00..000000000 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ /dev/null @@ -1,143 +0,0 @@ - - - - Debug - AnyCPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5} - Library - Python.EmbeddingTest - Python.EmbeddingTest - bin\Python.EmbeddingTest.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - 7.3 - true - prompt - - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - - - ..\..\packages\NUnit.3.12.0\lib\net40\nunit.framework.dll - - - ..\..\packages\System.ValueTuple.4.5.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Python.Runtime - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj deleted file mode 100644 index 070d87835..000000000 --- a/src/runtime/Python.Runtime.csproj +++ /dev/null @@ -1,188 +0,0 @@ - - - - Debug - AnyCPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Library - Python.Runtime - Python.Runtime - bin\Python.Runtime.xml - bin\ - v4.0 - - 1591 - ..\..\ - $(SolutionDir)\bin\ - Properties - 7.3 - true - false - ..\pythonnet.snk - - - - - - PYTHON2;PYTHON27;UCS4 - true - pdbonly - - - PYTHON3;PYTHON38;UCS4 - true - pdbonly - - - true - PYTHON2;PYTHON27;UCS4;TRACE;DEBUG - false - full - - - true - PYTHON3;PYTHON38;UCS4;TRACE;DEBUG - false - full - - - PYTHON2;PYTHON27;UCS2 - true - pdbonly - - - PYTHON3;PYTHON38;UCS2 - true - pdbonly - - - true - PYTHON2;PYTHON27;UCS2;TRACE;DEBUG - false - full - - - true - PYTHON3;PYTHON38;UCS2;TRACE;DEBUG - false - full - - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - clr.py - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj deleted file mode 100644 index 63526c060..000000000 --- a/src/testing/Python.Test.csproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - Debug - AnyCPU - {6F401A34-273B-450F-9A4C-13550BE0767B} - Library - Python.Test - Python.Test - bin\Python.Test.xml - bin\ - v4.0 - - 1591,0067 - ..\..\ - $(SolutionDir)\bin\ - 6 - false - ..\pythonnet.snk - prompt - - - x86 - - - x64 - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - true - DEBUG;TRACE - full - - - - - true - pdbonly - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Python.Runtime - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - From d55a914b1cda596d1530b2dd506af9be0841920f Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 4 Sep 2020 13:52:59 -0700 Subject: [PATCH 221/240] fixed crash in SetError when PythonException does not have type or value also: introduced StealingReference type for C API parameters --- src/runtime/NewReference.cs | 30 ++++++++++++++++++++++++++++-- src/runtime/StealingReference.cs | 23 +++++++++++++++++++++++ src/runtime/exceptions.cs | 8 ++++---- src/runtime/pythonexception.cs | 23 +++++++++++++++++++---- src/runtime/runtime.cs | 6 +++++- 5 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 src/runtime/StealingReference.cs diff --git a/src/runtime/NewReference.cs b/src/runtime/NewReference.cs index 4c9f36ccc..85ebe3244 100644 --- a/src/runtime/NewReference.cs +++ b/src/runtime/NewReference.cs @@ -15,6 +15,20 @@ ref struct NewReference public static implicit operator BorrowedReference(in NewReference reference) => new BorrowedReference(reference.pointer); + /// + /// Creates from a nullable . + /// Increments the reference count accordingly. + /// + [Pure] + public static NewReference FromNullable(BorrowedReference reference) + { + if (reference.IsNull) return default; + + IntPtr address = reference.DangerousGetAddress(); + Runtime.XIncref(address); + return DangerousFromPointer(address); + } + /// /// Returns wrapper around this reference, which now owns /// the pointer. Sets the original reference to null, as it no longer owns it. @@ -44,6 +58,18 @@ public void Dispose() public static NewReference DangerousFromPointer(IntPtr pointer) => new NewReference {pointer = pointer}; + /// + /// Creates from a raw pointer + /// and writes null to the original location. + /// + [Pure] + public static NewReference DangerousMoveFromPointer(ref IntPtr pointer) + { + var pointerValue = pointer; + pointer = IntPtr.Zero; + return DangerousFromPointer(pointerValue); + } + public IntPtr DangerousMoveToPointer() { if (this.IsNull()) throw new NullReferenceException(); @@ -61,11 +87,11 @@ internal static bool IsNull(in NewReference reference) => reference.pointer == IntPtr.Zero; // TODO: return some static type - internal IntPtr Steal() + internal StealingReference Steal() { var result = this.pointer; this.pointer = IntPtr.Zero; - return result; + return StealingReference.DangerousFromPointer(result); } } diff --git a/src/runtime/StealingReference.cs b/src/runtime/StealingReference.cs new file mode 100644 index 000000000..da4b67fda --- /dev/null +++ b/src/runtime/StealingReference.cs @@ -0,0 +1,23 @@ +namespace Python.Runtime +{ + using System; + using System.Diagnostics.Contracts; + + /// + /// Represents a reference to a Python object, that is being stolen by a C API. + /// + [NonCopyable] + ref struct StealingReference + { + IntPtr pointer; + + /// + /// Creates from a raw pointer + /// + [Pure] + public static StealingReference DangerousFromPointer(IntPtr pointer) + => new StealingReference { pointer = pointer}; + + public IntPtr DangerousGetAddressOrNull() => this.pointer; + } +} diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 1c483e7e6..03f5b4e18 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -283,10 +283,10 @@ public static void SetError(Exception e) var pe = e as PythonException; if (pe != null) { - Runtime.XIncref(pe.PyType); - Runtime.XIncref(pe.PyValue); - Runtime.XIncref(pe.PyTB); - Runtime.PyErr_Restore(pe.PyType, pe.PyValue, pe.PyTB); + Runtime.PyErr_Restore( + NewReference.FromNullable(pe.PythonType).Steal(), + NewReference.FromNullable(pe.Value).Steal(), + NewReference.FromNullable(pe.Traceback).Steal()); return; } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index dfca2c70c..45cf43572 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -236,10 +236,10 @@ static string TracebackHandleToString(BorrowedReference tracebackHandle) { public void Restore() { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.PyErr_Restore(_pyType, _pyValue, _pyTB); - _pyType = IntPtr.Zero; - _pyValue = IntPtr.Zero; - _pyTB = IntPtr.Zero; + Runtime.PyErr_Restore( + NewReference.DangerousMoveFromPointer(ref _pyType).Steal(), + NewReference.DangerousMoveFromPointer(ref _pyValue).Steal(), + NewReference.DangerousMoveFromPointer(ref _pyTB).Steal()); PythonEngine.ReleaseLock(gs); } @@ -254,6 +254,11 @@ public IntPtr PyType get { return _pyType; } } + /// + /// Type of the exception (nullable). + /// + internal BorrowedReference PythonType => new BorrowedReference(_pyType); + /// /// PyValue Property /// @@ -265,6 +270,11 @@ public IntPtr PyValue get { return _pyValue; } } + /// + /// Exception object value (nullable). + /// + internal BorrowedReference Value => new BorrowedReference(_pyValue); + /// /// PyTB Property /// @@ -276,6 +286,11 @@ public IntPtr PyTB get { return _pyTB; } } + /// + /// Traceback (nullable). + /// + internal BorrowedReference Traceback => new BorrowedReference(_pyTB); + /// /// Message Property /// diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 7a17d2ff7..954c6286b 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1900,7 +1900,11 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) internal static void PyErr_Fetch(out NewReference type, out NewReference value, out NewReference traceback) => Delegates.PyErr_Fetch(out type, out value, out traceback); - internal static void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb) => Delegates.PyErr_Restore(ob, val, tb); + internal static void PyErr_Restore(StealingReference ob, StealingReference val, StealingReference tb) + => Delegates.PyErr_Restore( + ob.DangerousGetAddressOrNull(), + val.DangerousGetAddressOrNull(), + tb.DangerousGetAddressOrNull()); internal static void PyErr_Clear() => Delegates.PyErr_Clear(); From 8e1d4dbf7b0e647482b302bf2ce7ad36f0b9d0f5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 4 Sep 2020 14:24:45 -0700 Subject: [PATCH 222/240] fixed crash in ToArray when sequence explicitly denies __len__ --- src/runtime/converter.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 68dce2597..7e6e84d7a 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -761,6 +761,11 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s bool IsSeqObj = Runtime.PySequence_Check(value); var len = IsSeqObj ? Runtime.PySequence_Size(value) : -1; + if (IsSeqObj && len < 0) + { + // for the sequences, that explicitly deny calling __len__() + Exceptions.Clear(); + } var IterObject = Runtime.PyObject_GetIter(new BorrowedReference(value)); @@ -776,8 +781,9 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s var listType = typeof(List<>); var constructedListType = listType.MakeGenericType(elementType); - IList list = IsSeqObj ? (IList) Activator.CreateInstance(constructedListType, new Object[] {(int) len}) : - (IList) Activator.CreateInstance(constructedListType); + IList list = IsSeqObj && len > 0 + ? (IList) Activator.CreateInstance(constructedListType, args: (int)len) + : (IList) Activator.CreateInstance(constructedListType); NewReference item; while (!(item = Runtime.PyIter_Next(IterObject)).IsNull()) From 04420579872705e9f96512816d9e6df26f44f893 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 4 Sep 2020 18:49:26 -0700 Subject: [PATCH 223/240] prevent crash during debugging when attempting to inspect PyObject without GIL --- src/runtime/debughelper.cs | 13 ++++++++++--- src/runtime/pyobject.cs | 5 +++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index 5e3fad8f0..89bdd23f9 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -141,9 +141,16 @@ public static void PrintHexBytes(byte[] bytes) [Conditional("DEBUG")] public static void EnsureGIL() { - if (Runtime.PythonVersion >= new Version(3,4)) { - Debug.Assert(Runtime.PyGILState_Check() == 1, "GIL must be acquired"); - } + Debug.Assert(HaveInterpreterLock() != false, "GIL must be acquired"); + } + + public static bool? HaveInterpreterLock() + { + // not supported on older version + if (Runtime.PythonVersion < new Version(3, 4)) + return null; + + return Runtime.PyGILState_Check() == 1; } [Conditional("DEBUG")] diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index d19765111..61003c42a 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -20,6 +20,7 @@ public interface IPyDisposable : IDisposable /// PY3: https://docs.python.org/3/c-api/object.html /// for details. /// + [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")] public class PyObject : DynamicObject, IEnumerable, IPyDisposable { #if TRACE_ALLOC @@ -1085,6 +1086,10 @@ public override string ToString() return result; } + string DebuggerDisplay => DebugUtil.HaveInterpreterLock() != false + ? this.ToString() + : $"pyobj at 0x{this.obj:X} (get Py.GIL to see more info)"; + /// /// Equals Method From 1c36bc011252053d404b0aa78ecd51de26878be3 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 13 Oct 2020 02:53:46 -0700 Subject: [PATCH 224/240] Fixed polyfill for TypeBuilder.CreateType (#1261) https://github.com/pythonnet/pythonnet/issues/1228 --- src/runtime/Python.Runtime.15.csproj | 2 +- src/runtime/polyfill/ReflectionPolifills.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 877e55a31..09ad7d323 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -77,7 +77,7 @@ - + diff --git a/src/runtime/polyfill/ReflectionPolifills.cs b/src/runtime/polyfill/ReflectionPolifills.cs index 7e6231935..b2c60a83e 100644 --- a/src/runtime/polyfill/ReflectionPolifills.cs +++ b/src/runtime/polyfill/ReflectionPolifills.cs @@ -16,7 +16,7 @@ public static AssemblyBuilder DefineDynamicAssembly(this AppDomain appDomain, As public static Type CreateType(this TypeBuilder typeBuilder) { - return typeBuilder.GetTypeInfo().GetType(); + return typeBuilder.CreateTypeInfo(); } #endif #if NETFX From fa4cebda99e180e0fa5045cacb41d1f16e224a22 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 17 Oct 2020 12:57:49 -0700 Subject: [PATCH 225/240] PyIter.MoveNext: propagate Python exception if any --- src/runtime/pyiter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index 8841a471c..e04f4afed 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -37,6 +37,9 @@ public bool MoveNext() using var next = Runtime.PyIter_Next(Reference); if (next.IsNull()) { + if (Exceptions.ErrorOccurred()) + throw PythonException.ThrowLastAsClrException(); + // dispose of the previous object, if there was one _current = null; return false; From 61f694271e1652412295ecc6616a3dc8ed605914 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 17 Oct 2020 13:06:33 -0700 Subject: [PATCH 226/240] enable creating PyIter from existing PyObject --- src/runtime/pyiter.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index e04f4afed..ca4fd7c92 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -24,6 +24,19 @@ public class PyIter : PyObject, IEnumerator public PyIter(IntPtr ptr) : base(ptr) { } + /// + /// Creates new from an untyped reference to Python object. + /// + public PyIter(PyObject pyObject) : base(FromPyObject(pyObject)) { } + static BorrowedReference FromPyObject(PyObject pyObject) { + if (pyObject is null) throw new ArgumentNullException(nameof(pyObject)); + + if (!Runtime.PyIter_Check(pyObject.Reference)) + throw new ArgumentException("Object does not support iterator protocol"); + + return pyObject.Reference; + } + internal PyIter(BorrowedReference reference) : base(reference) { } protected override void Dispose(bool disposing) From 9cc2b45fa9c499634635feb900b303d99056eabc Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 17 Oct 2020 13:11:14 -0700 Subject: [PATCH 227/240] bumped version to 3.0.3 --- src/runtime/Python.Runtime.15.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 09ad7d323..411e1970a 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -9,7 +9,7 @@ true true This software is part of Gradient: https://losttech.software/gradient.html - 3.0.2 + 3.0.3 true true snupkg From 7555dec933547b6d35f658ed950d18259e140540 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sun, 18 Oct 2020 14:01:57 -0700 Subject: [PATCH 228/240] fixed debug assert when inheriting from RuntimeError This simplifies and generalizes logic for allocating extra fields when inheriting from Python classes. The new class instance size is base_size + clr_pointer_size + (optional, only if not in the base already) weaklist&dict --- src/embed_tests/Inheritance.cs | 20 ++++++++++++++++ src/runtime/interop.cs | 14 ++++++----- src/runtime/typemanager.cs | 44 ++++++++++++++++------------------ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/embed_tests/Inheritance.cs b/src/embed_tests/Inheritance.cs index 109486af8..15ba44a1b 100644 --- a/src/embed_tests/Inheritance.cs +++ b/src/embed_tests/Inheritance.cs @@ -104,6 +104,26 @@ public void PythonCanSetAdHocAttributes() { Assert.AreEqual(expected: Inherited.X, actual); } } + + [Test] + public void FromException() { + using var _ = Py.GIL(); + var runtimeError = PythonEngine.Eval("RuntimeError"); + PythonEngine.InteropConfiguration.PythonBaseTypeProviders.Add( + new TestRuntimeError.BaseProvdier()); + var instance = new TestRuntimeError().ToPython(); + bool isRuntimeError = PyIsInstance(instance, runtimeError); + Assert.IsTrue(isRuntimeError); + } + } + + public class TestRuntimeError: Exception { + internal class BaseProvdier: IPythonBaseTypeProvider { + public IEnumerable GetBaseTypes(Type type, IList existingBases) + => type != typeof(TestRuntimeError) + ? existingBases + : new[] { PythonEngine.Eval("RuntimeError") }; + } } class CustomBaseTypeProvider : IPythonBaseTypeProvider { diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 5ed8d91d0..6b952a2bc 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -111,16 +111,18 @@ internal static void ClrGcHandleOffsetAssertSanity(int offset) /// /// Returns dict offset in instances of the specified /// - public static int TypeDictOffset(BorrowedReference type) { + public static unsafe int TypeDictOffset(BorrowedReference type) { +#if DEBUG if (!Runtime.PyType_Check(type)) throw new ArgumentException("Bad object type"); +#endif - return IsExceptionSubtype(type) - ? ExceptionOffset.ob_dict - : ob_dict; + IntPtr dictoffset = type.DangerousGetAddress() + TypeOffset.tp_dictoffset; + int dict = *((int*)(dictoffset)); + Debug.Assert(dict > 0 && dict < 100_000); + return dict; } - public static int TypeDictOffset(IntPtr type) - => TypeDictOffset(new BorrowedReference(type)); + public static int TypeDictOffset() => ob_dict; public static int Size(IntPtr ob) { if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 8214cc214..3ec7fd00e 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -88,7 +88,7 @@ internal static IntPtr CreateType(Type impl) // Set tp_basicsize to the size of our managed instance objects. Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); - var offset = (IntPtr)ObjectOffset.TypeDictOffset(type); + var offset = (IntPtr)ObjectOffset.TypeDictOffset(); Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset); InitializeSlots(type, impl); @@ -109,21 +109,11 @@ internal static IntPtr CreateType(Type impl) return type; } - internal static IntPtr CreateType(ManagedType impl, Type clrType) { string name = GetPythonTypeName(clrType); int ob_size; - int tp_dictoffset = ObjectOffset.TypeDictOffset(Runtime.PyTypeType); - - // XXX Hack, use a different base class for System.Exception - // Python 2.5+ allows new style class exceptions but they *must* - // subclass BaseException (or better Exception). - if (typeof(Exception).IsAssignableFrom(clrType)) - { - tp_dictoffset = ObjectOffset.TypeDictOffset(Exceptions.Exception); - } IntPtr type = AllocateTypeObject(name, typeType: Runtime.PyCLRMetaType); @@ -159,22 +149,29 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Marshal.WriteIntPtr(type, TypeOffset.tp_bases, baseTuple.Reference.DangerousIncRefOrNull()); } - int baseSize = primaryBase == Runtime.PyBaseObjectType ? ObjectOffset.PyObject_HEAD_Size() - : primaryBase == Exceptions.Exception ? ExceptionOffset.Size() - : checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.tp_basicsize)); - if (!ManagedType.IsManagedType(primaryBase)) - { + ob_size = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.tp_basicsize)); + void InheritOrAllocate(int typeField) { + int value = Marshal.ReadInt32(primaryBase, typeField); + if (value == 0) { + Marshal.WriteIntPtr(type, typeField, new IntPtr(ob_size)); + ob_size += IntPtr.Size; + } else { + Marshal.WriteIntPtr(type, typeField, new IntPtr(value)); + } + } + + InheritOrAllocate(TypeOffset.tp_dictoffset); + InheritOrAllocate(TypeOffset.tp_weaklistoffset); + + if (!ManagedType.IsManagedType(primaryBase)) { // base type is a Python type, so we must allocate additional space for GC handle - extraTypeDataOffset = baseSize; + extraTypeDataOffset = ob_size; ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); - ob_size = baseSize + MetaType.ExtraTypeDataSize; - } else - { + ob_size += MetaType.ExtraTypeDataSize; + } else { extraTypeDataOffset = checked((int)Marshal.ReadIntPtr(primaryBase, TypeOffset.clr_gchandle_offset)); ObjectOffset.ClrGcHandleOffsetAssertSanity(extraTypeDataOffset); - ob_size = baseSize; } - Debug.Assert(extraTypeDataOffset > tp_dictoffset); } catch (Exception error) { @@ -186,7 +183,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); - Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, (IntPtr)tp_dictoffset); Marshal.WriteIntPtr(type, TypeOffset.clr_gchandle_offset, (IntPtr)extraTypeDataOffset); var flags = TypeFlags.Default; @@ -206,6 +202,8 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) return IntPtr.Zero; } + Debug.Assert(extraTypeDataOffset > Marshal.ReadInt32(type, TypeOffset.tp_dictoffset)); + IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict); string mn = clrType.Namespace ?? ""; IntPtr mod = Runtime.PyString_FromString(mn); From dfe85daa36dec333b9ecaea93539f04a18a373d7 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 23 Oct 2020 12:06:31 -0700 Subject: [PATCH 229/240] don't hide real C# exception when attempt to get property value fails --- src/runtime/propertyobject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index 0cb6e85bf..afc975d6e 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -56,7 +56,8 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) } catch (Exception e) { - return Exceptions.RaiseTypeError(e.Message); + Exceptions.SetError(e); + return IntPtr.Zero; } } From 8b74b3188c80dc59abf234f0069f004f72f3d844 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 23 Oct 2020 12:08:03 -0700 Subject: [PATCH 230/240] property descriptor made visible on the reflected class for instance properties --- src/embed_tests/Inspect.cs | 9 +++++++++ src/runtime/propertyobject.cs | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/embed_tests/Inspect.cs b/src/embed_tests/Inspect.cs index e217d5b30..7fbed6b72 100644 --- a/src/embed_tests/Inspect.cs +++ b/src/embed_tests/Inspect.cs @@ -26,6 +26,15 @@ public void BoundMethodsAreInspectable() { } } + [Test] + public void InstancePropertiesVisibleOnClass() { + var uri = new Uri("http://example.org").ToPython(); + var uriClass = uri.GetPythonType(); + var property = uriClass.GetAttr(nameof(Uri.AbsoluteUri)); + var pyProp = ManagedType.GetManagedObject(property.Reference); + Assert.AreEqual(nameof(Uri.AbsoluteUri), pyProp.info.Name); + } + class Class { public void Method(int a, int b = 10) { } public void Method(int a, object b) { } diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index afc975d6e..a2be4fa69 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -9,7 +9,7 @@ namespace Python.Runtime /// internal class PropertyObject : ExtensionType { - private PropertyInfo info; + internal PropertyInfo info; private MethodInfo getter; private MethodInfo setter; @@ -44,9 +44,9 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { if (!getter.IsStatic) { - Exceptions.SetError(Exceptions.TypeError, - "instance property must be accessed through a class instance"); - return IntPtr.Zero; + Runtime.XIncref(ds); + // unbound property + return ds; } try From 4dbfaaf86aff8406fd1c083f22bf9ddff0a7d555 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 7 Nov 2020 12:03:29 -0800 Subject: [PATCH 231/240] bumped version to 3.0.4 --- src/runtime/Python.Runtime.15.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 411e1970a..5fef0b6b5 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -9,7 +9,7 @@ true true This software is part of Gradient: https://losttech.software/gradient.html - 3.0.3 + 3.0.4 true true snupkg From b0b7b65d28e499bb736208b8adea5f6fdf956c3c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 7 Nov 2020 12:12:12 -0800 Subject: [PATCH 232/240] disable legacy "Full" DebugType --- src/runtime/Python.Runtime.15.csproj | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 5fef0b6b5..33715104a 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -37,14 +37,6 @@ $(PYTHONNET_MULTIRUNTIME_DEFINE_CONSTANTS) - - false - full - - - true - portable - $(DefineConstants);$(PythonMultiRuntimeDefineConstants);TRACE;DEBUG From ef72455f6c1a61c035047b9b8270709160d22638 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 13 Nov 2020 22:32:12 -0800 Subject: [PATCH 233/240] PyObject.As* methods set inner exception when the cause of conversion failure is known --- src/runtime/pyobject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 61003c42a..40758ef53 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -135,7 +135,7 @@ public static PyObject FromManagedObject(object ob) public object AsManagedObject(Type t) { object result; - if (!Converter.ToManaged(obj, t, out result, false)) + if (!Converter.ToManaged(obj, t, out result, setError: true)) { throw new InvalidCastException("cannot convert object to target type", innerException: PythonException.FromPyErrOrNull()); From ad7f83b026fd13c725d83e0739d93a7bb7e9d83c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 20 Nov 2020 18:58:36 -0800 Subject: [PATCH 234/240] PyObject.Length no longer returns 0 when it is impossible to determine length --- src/runtime/pyobject.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 40758ef53..500a9156a 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -657,10 +657,6 @@ public virtual void DelItem(int index) /// /// Length Method /// - /// - /// Returns the length for objects that support the Python sequence - /// protocol, or 0 if the object does not support the protocol. - /// public virtual long Length() { DebugUtil.EnsureGIL(); @@ -668,8 +664,7 @@ public virtual long Length() var s = Runtime.PyObject_Size(obj); if (s < 0) { - Runtime.PyErr_Clear(); - return 0; + throw PythonException.ThrowLastAsClrException(); } return s; } From 2b5902f306907c86bac6f06ea87055d330e6d776 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 5 Dec 2020 21:02:05 -0800 Subject: [PATCH 235/240] NumPy array iteration test --- src/embed_tests/NumPyTests.cs | 46 +++++++++++++++++++++-------------- src/runtime/pyiter.cs | 2 +- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/embed_tests/NumPyTests.cs b/src/embed_tests/NumPyTests.cs index 4c84905bb..7c7779ce9 100644 --- a/src/embed_tests/NumPyTests.cs +++ b/src/embed_tests/NumPyTests.cs @@ -21,20 +21,22 @@ public void Dispose() PythonEngine.Shutdown(); } - [Test] - public void TestReadme() - { - dynamic np; - try - { + static PyObject GetNumPy() { + PyObject np; + try { np = Py.Import("numpy"); - } - catch (PythonException) - { + } catch (PythonException) { Assert.Inconclusive("Numpy or dependency not installed"); - return; + throw; } - + return np; + } + + [Test] + public void TestReadme() + { + dynamic np = GetNumPy(); + Assert.AreEqual("1.0", np.cos(np.pi * 2).ToString()); dynamic sin = np.sin; @@ -55,13 +57,7 @@ public void TestReadme() [Test] public void MultidimensionalNumPyArray() { - PyObject np; - try { - np = Py.Import("numpy"); - } catch (PythonException) { - Assert.Inconclusive("Numpy or dependency not installed"); - return; - } + PyObject np = GetNumPy(); var array = new[,] { { 1, 2 }, { 3, 4 } }; var ndarray = np.InvokeMethod("asarray", array.ToPython()); @@ -69,5 +65,19 @@ public void MultidimensionalNumPyArray() Assert.AreEqual(1, ndarray[(0, 0).ToPython()].As()); Assert.AreEqual(array[1, 0], ndarray[(1, 0).ToPython()].As()); } + + [Test] + public void Iterate() + { + PyObject np = GetNumPy(); + + var size = new[] { 3, 2 }; + var ndarray = np.InvokeMethod("zeros", size.ToPython()); + var iterator = ndarray.GetIterator(); + Assert.True(iterator.MoveNext()); + Assert.True(iterator.MoveNext()); + Assert.True(iterator.MoveNext()); + Assert.False(iterator.MoveNext()); + } } } diff --git a/src/runtime/pyiter.cs b/src/runtime/pyiter.cs index ca4fd7c92..7be981678 100644 --- a/src/runtime/pyiter.cs +++ b/src/runtime/pyiter.cs @@ -25,7 +25,7 @@ public PyIter(IntPtr ptr) : base(ptr) { } /// - /// Creates new from an untyped reference to Python object. + /// Creates new from an untyped reference to Python iterator object. /// public PyIter(PyObject pyObject) : base(FromPyObject(pyObject)) { } static BorrowedReference FromPyObject(PyObject pyObject) { From 5dff25ff4fb0fddc043e86c5faf9fe5fb8aea4d3 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 5 Dec 2020 21:02:22 -0800 Subject: [PATCH 236/240] improved a few debug assertion messages --- src/runtime/interop.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 6b952a2bc..1084bf39d 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -85,7 +85,8 @@ public static int InstanceGCHandle(BorrowedReference type) { Debug.Assert(ManagedType.IsManagedType(type)); var meta = Runtime.PyObject_TYPE(type); if (Runtime.PyCLRMetaType != IntPtr.Zero && meta.DangerousGetAddress() != Runtime.PyCLRMetaType) - Debug.Assert(new PyObject(meta).ToString() == ""); + Debug.Assert(new PyObject(meta).ToString() == "", + $"Bad metatype: {new PyObject(meta)}"); #endif int offset = (int)Marshal.ReadIntPtr(type.DangerousGetAddress(), TypeOffset.clr_gchandle_offset); #if DEBUG @@ -106,7 +107,7 @@ public static int ReflectedObjectGCHandle(BorrowedReference reflectedManagedObje static void AssertIsClrType(IntPtr tp) => Debug.Assert(Runtime.PyObject_TYPE(tp) == Runtime.PyCLRMetaType); [Conditional("DEBUG")] internal static void ClrGcHandleOffsetAssertSanity(int offset) - => Debug.Assert(offset > 0 && offset < 1024 * 4, "GC handle offset is insane"); + => Debug.Assert(offset > 0 && offset < 1024 * 4, $"GC handle offset is insane: {offset}"); /// /// Returns dict offset in instances of the specified From 0dc9fa5e0f42feb9b48c553066edeae082e5102c Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 5 Dec 2020 22:10:18 -0800 Subject: [PATCH 237/240] allow Python to overwrite .NET methods --- src/embed_tests/CallableObject.cs | 12 ++++++++++++ src/runtime/extensiontype.cs | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/embed_tests/CallableObject.cs b/src/embed_tests/CallableObject.cs index 76b93c62e..553a666e6 100644 --- a/src/embed_tests/CallableObject.cs +++ b/src/embed_tests/CallableObject.cs @@ -38,6 +38,18 @@ public void CallMethodCanBeInheritedFromPython() { } } + [Test] + public void CanOverwriteCall() { + var callViaInheritance = new CallViaInheritance(); + using var _ = Py.GIL(); + using var scope = Py.CreateScope(); + scope.Set("o", callViaInheritance); + scope.Exec("orig_call = o.Call"); + scope.Exec("o.Call = lambda a: orig_call(a*7)"); + int result = scope.Eval("o.Call(5)"); + Assert.AreEqual(105, result); + } + class Doubler { public int __call__(int arg) => 2 * arg; } diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index b7f4996ca..8fe826037 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -76,17 +76,6 @@ public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) } - /// - /// Default __set__ implementation - this prevents descriptor instances - /// being silently replaced in a type __dict__ by default __setattr__. - /// - public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) - { - Exceptions.SetError(Exceptions.AttributeError, "attribute is read-only"); - return -1; - } - - /// /// Default dealloc implementation. /// From 004b3651d3d11e9400e59cae701d16a954abaca5 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Sat, 5 Dec 2020 22:58:34 -0800 Subject: [PATCH 238/240] fixed bad GetManagedObject calls in CLR-based descriptor implementations --- src/embed_tests/Inspect.cs | 2 +- src/runtime/constructorbinding.cs | 22 +++++++++++++--------- src/runtime/eventbinding.cs | 5 +++-- src/runtime/eventobject.cs | 8 ++++---- src/runtime/extensiontype.cs | 17 +++++++++++++++++ src/runtime/fieldobject.cs | 10 ++++++---- src/runtime/managedtype.cs | 4 ---- src/runtime/metatype.cs | 2 +- src/runtime/methodbinding.cs | 11 ++++++----- src/runtime/methodobject.cs | 2 +- src/runtime/propertyobject.cs | 10 ++++++---- 11 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/embed_tests/Inspect.cs b/src/embed_tests/Inspect.cs index 7fbed6b72..83fb923e1 100644 --- a/src/embed_tests/Inspect.cs +++ b/src/embed_tests/Inspect.cs @@ -31,7 +31,7 @@ public void InstancePropertiesVisibleOnClass() { var uri = new Uri("http://example.org").ToPython(); var uriClass = uri.GetPythonType(); var property = uriClass.GetAttr(nameof(Uri.AbsoluteUri)); - var pyProp = ManagedType.GetManagedObject(property.Reference); + var pyProp = ExtensionType.GetManagedObject(property.Reference); Assert.AreEqual(nameof(Uri.AbsoluteUri), pyProp.info.Name); } diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs index 839215cc7..c052a0078 100644 --- a/src/runtime/constructorbinding.cs +++ b/src/runtime/constructorbinding.cs @@ -40,7 +40,7 @@ public ConstructorBinding(Type type, BorrowedReference pyTypeHndl, ConstructorBi /// of a .Overloads[pyTypeOrType...] syntax to allow explicit ctor overload /// selection. /// - /// PyObject* to a Constructors wrapper + /// PyObject* to a Constructors wrapper /// /// the instance that the attribute was accessed through, /// or None when the attribute is accessed through the owner @@ -59,9 +59,10 @@ public ConstructorBinding(Type type, BorrowedReference pyTypeHndl, ConstructorBi /// the attribute was accessed through, or None when the attribute is accessed through the owner. /// This method should return the (computed) attribute value or raise an AttributeError exception. /// - public static IntPtr tp_descr_get(IntPtr op, IntPtr instance, IntPtr owner) + public static IntPtr tp_descr_get(IntPtr opRaw, IntPtr instance, IntPtr owner) { - var self = (ConstructorBinding)GetManagedObject(op); + var op = new BorrowedReference(opRaw); + var self = GetManagedObject(op); if (self == null) { return IntPtr.Zero; @@ -86,9 +87,10 @@ public static IntPtr tp_descr_get(IntPtr op, IntPtr instance, IntPtr owner) /// Return element of o corresponding to the object key or NULL on failure. /// This is the equivalent of the Python expression o[key]. /// - public static IntPtr mp_subscript(IntPtr op, IntPtr key) + public static IntPtr mp_subscript(IntPtr opRaw, IntPtr key) { - var self = (ConstructorBinding)GetManagedObject(op); + var op = new BorrowedReference(opRaw); + var self = GetManagedObject(op); Type[] types = Runtime.PythonArgsToTypeArray(key); if (types == null) @@ -110,9 +112,10 @@ public static IntPtr mp_subscript(IntPtr op, IntPtr key) /// /// ConstructorBinding __repr__ implementation [borrowed from MethodObject]. /// - public static IntPtr tp_repr(IntPtr ob) + public static IntPtr tp_repr(IntPtr obRaw) { - var self = (ConstructorBinding)GetManagedObject(ob); + var ob = new BorrowedReference(obRaw); + var self = GetManagedObject(ob); if (self.repr != IntPtr.Zero) { Runtime.XIncref(self.repr); @@ -139,9 +142,10 @@ public static IntPtr tp_repr(IntPtr ob) /// /// ConstructorBinding dealloc implementation. /// - public new static void tp_dealloc(IntPtr ob) + public new static void tp_dealloc(IntPtr obRaw) { - var self = (ConstructorBinding)GetManagedObject(ob); + var ob = new BorrowedReference(obRaw); + var self = GetManagedObject(ob); Runtime.XDecref(self.repr); Runtime.XDecref(self.pyTypeHndl); ExtensionType.FinalizeObject(self); diff --git a/src/runtime/eventbinding.cs b/src/runtime/eventbinding.cs index b8b4c82ad..8b3f6ee43 100644 --- a/src/runtime/eventbinding.cs +++ b/src/runtime/eventbinding.cs @@ -9,6 +9,7 @@ internal class EventBinding : ExtensionType { private EventObject e; private IntPtr target; + internal BorrowedReference Target => new BorrowedReference(target); public EventBinding(EventObject e, IntPtr target) { @@ -31,7 +32,7 @@ public static IntPtr nb_inplace_add(IntPtr ob, IntPtr arg) return IntPtr.Zero; } - if (!self.e.AddEventHandler(self.target, arg)) + if (!self.e.AddEventHandler(self.Target, arg)) { return IntPtr.Zero; } @@ -54,7 +55,7 @@ public static IntPtr nb_inplace_subtract(IntPtr ob, IntPtr arg) return IntPtr.Zero; } - if (!self.e.RemoveEventHandler(self.target, arg)) + if (!self.e.RemoveEventHandler(self.Target, arg)) { return IntPtr.Zero; } diff --git a/src/runtime/eventobject.cs b/src/runtime/eventobject.cs index 5f18c4609..6d6bb59f0 100644 --- a/src/runtime/eventobject.cs +++ b/src/runtime/eventobject.cs @@ -24,12 +24,12 @@ public EventObject(EventInfo info) /// /// Register a new Python object event handler with the event. /// - internal bool AddEventHandler(IntPtr target, IntPtr handler) + internal bool AddEventHandler(BorrowedReference target, IntPtr handler) { object obj = null; if (target != IntPtr.Zero) { - var co = (CLRObject)GetManagedObject(target); + var co = (CLRObject)ManagedType.GetManagedObject(target); obj = co.inst; } @@ -69,12 +69,12 @@ internal bool AddEventHandler(IntPtr target, IntPtr handler) /// /// Remove the given Python object event handler. /// - internal bool RemoveEventHandler(IntPtr target, IntPtr handler) + internal bool RemoveEventHandler(BorrowedReference target, IntPtr handler) { object obj = null; if (target != IntPtr.Zero) { - var co = (CLRObject)GetManagedObject(target); + var co = (CLRObject)ManagedType.GetManagedObject(target); obj = co.inst; } diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index 8fe826037..77e09762c 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -46,6 +46,23 @@ public ExtensionType() } + internal static T GetManagedObject(BorrowedReference ob) + where T : ExtensionType + => (T)GetManagedObject(ob, ObjectOffset.GetDefaultGCHandleOffset()); + [Obsolete] + internal static new ExtensionType GetManagedObject(IntPtr ob) + => (ExtensionType)GetManagedObject(new BorrowedReference(ob), ObjectOffset.GetDefaultGCHandleOffset()); + [Obsolete] + internal static new ExtensionType GetManagedObject(BorrowedReference ob) + => (ExtensionType)GetManagedObject(ob, ObjectOffset.GetDefaultGCHandleOffset()); + + internal static bool IsExtensionType(BorrowedReference tp) + { + if (!IsManagedType(tp)) return false; + var metaType = Runtime.PyObject_TYPE(tp); + return metaType == Runtime.PyTypeType; + } + /// /// Common finalization code to support custom tp_deallocs. /// diff --git a/src/runtime/fieldobject.cs b/src/runtime/fieldobject.cs index d0b854c82..e7910b044 100644 --- a/src/runtime/fieldobject.cs +++ b/src/runtime/fieldobject.cs @@ -20,8 +20,9 @@ public FieldObject(FieldInfo info) /// value of the field on the given object. The returned value /// is converted to an appropriately typed Python object. /// - public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) + public static IntPtr tp_descr_get(IntPtr ds, IntPtr obRaw, IntPtr tp) { + var ob = new BorrowedReference(obRaw); var self = (FieldObject)GetManagedObject(ds); object result; @@ -54,7 +55,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) try { - var co = (CLRObject)GetManagedObject(ob); + var co = (CLRObject)ManagedType.GetManagedObject(ob); result = info.GetValue(co.inst); return Converter.ToPython(result); } @@ -70,8 +71,9 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) /// a field based on the given Python value. The Python value must be /// convertible to the type of the field. /// - public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) + public new static int tp_descr_set(IntPtr ds, IntPtr obRaw, IntPtr val) { + var ob = new BorrowedReference(obRaw); var self = (FieldObject)GetManagedObject(ds); object newval; @@ -114,7 +116,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { if (!is_static) { - var co = (CLRObject)GetManagedObject(ob); + var co = (CLRObject)ManagedType.GetManagedObject(ob); info.SetValue(co.inst, newval); } else diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 8d3a00bd5..870b8722b 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -51,10 +51,6 @@ internal static ManagedType GetManagedObject(BorrowedReference ob) internal static ManagedType GetManagedObject(IntPtr ob) => GetManagedObject(new BorrowedReference(ob)); - internal static T GetManagedObject(BorrowedReference ob) - where T : ExtensionType - => (T)GetManagedObject(ob, ObjectOffset.GetDefaultGCHandleOffset()); - internal static ManagedType GetManagedObject(BorrowedReference ob, int gcHandleOffset) { if (ob.IsNull) throw new ArgumentNullException(nameof(ob)); diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 69b769293..0303dc1b0 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -197,7 +197,7 @@ public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) if (dt == Runtime.PyWrapperDescriptorType || dt == Runtime.PyMethodType - || typeof(ExtensionType).IsInstanceOfType(GetManagedObject(descr)) + || ExtensionType.IsExtensionType(new BorrowedReference(dt)) ) { IntPtr fp = Marshal.ReadIntPtr(dt, TypeOffset.tp_descr_set); diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index bab905208..c9851c947 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -16,7 +16,8 @@ internal class MethodBinding : ExtensionType internal MethodObject m; internal IntPtr target; internal IntPtr targetType; - internal BorrowedReference TargetReference => new BorrowedReference(this.target); + internal BorrowedReference Target => new BorrowedReference(this.target); + internal BorrowedReference TargetType => new BorrowedReference(this.targetType); public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) { @@ -197,7 +198,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) var disposeList = new List(); try { - IntPtr target = self.target; + var target = self.target; if (target == IntPtr.Zero && !self.m.IsStatic()) { @@ -221,14 +222,14 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) IntPtr superType = IntPtr.Zero; if (Runtime.PyObject_TYPE(target) != self.targetType) { - var inst = GetManagedObject(target) as CLRObject; + var inst = ManagedType.GetManagedObject(target) as CLRObject; if (inst?.inst is IPythonDerivedType) { - var baseType = GetManagedObject(self.targetType) as ClassBase; + var baseType = ManagedType.GetManagedObject(self.TargetType) as ClassBase; if (baseType != null) { string baseMethodName = "_" + baseType.type.Name + "__" + self.m.name; - using var baseMethod = Runtime.PyObject_GetAttrString(self.TargetReference, baseMethodName); + using var baseMethod = Runtime.PyObject_GetAttrString(self.Target, baseMethodName); if (!baseMethod.IsNull()) { BorrowedReference baseMethodType = Runtime.PyObject_TYPE(baseMethod); diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index 0be75ae4a..47332b831 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -178,7 +178,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) // this descriptor was defined on then it will be because the base class method // is being called via super(Derived, self).method(...). // In which case create a MethodBinding bound to the base class. - var obj = GetManagedObject(ob) as CLRObject; + var obj = ManagedType.GetManagedObject(ob) as CLRObject; if (obj != null && obj.inst.GetType() != self.type && obj.inst is IPythonDerivedType diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index a2be4fa69..728988bba 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -28,8 +28,9 @@ static PropertyObject GetInstance(IntPtr ob) /// value of the property on the given object. The returned value /// is converted to an appropriately typed Python object. /// - public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) + public static IntPtr tp_descr_get(IntPtr ds, IntPtr obRaw, IntPtr tp) { + var ob = new BorrowedReference(obRaw); var self = GetInstance(ds); MethodInfo getter = self.getter; object result; @@ -61,7 +62,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) } } - var co = GetManagedObject(ob) as CLRObject; + var co = ManagedType.GetManagedObject(ob) as CLRObject; if (co == null) { return Exceptions.RaiseTypeError("invalid target"); @@ -89,8 +90,9 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) /// a property based on the given Python value. The Python value must /// be convertible to the type of the property. /// - public new static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) + public new static int tp_descr_set(IntPtr ds, IntPtr obRaw, IntPtr val) { + var ob = new BorrowedReference(obRaw); var self = GetInstance(ds); MethodInfo setter = self.setter; object newval; @@ -128,7 +130,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) { if (!is_static) { - var co = GetManagedObject(ob) as CLRObject; + var co = ManagedType.GetManagedObject(ob) as CLRObject; if (co == null) { Exceptions.RaiseTypeError("invalid target"); From cae2d32729a35fb31f53fd694464f5c44392b896 Mon Sep 17 00:00:00 2001 From: Victor Milovanov Date: Fri, 18 Dec 2020 21:10:07 -0800 Subject: [PATCH 239/240] bumped version to 3.0.5 --- src/runtime/Python.Runtime.15.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj index 33715104a..cd181c982 100644 --- a/src/runtime/Python.Runtime.15.csproj +++ b/src/runtime/Python.Runtime.15.csproj @@ -9,7 +9,7 @@ true true This software is part of Gradient: https://losttech.software/gradient.html - 3.0.4 + 3.0.5 true true snupkg From e6c75c223774d8b027e63e41d68242a56f1a9b5c Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sun, 18 Apr 2021 16:04:57 -0700 Subject: [PATCH 240/240] removed unused dot-net MyGet Feed --- NuGet.config | 1 - 1 file changed, 1 deletion(-) diff --git a/NuGet.config b/NuGet.config index 5210cd6c9..ed9d41057 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,6 @@ - \ No newline at end of file