From 10a2f8f661bcf616bce5f132db8603dd4b235a13 Mon Sep 17 00:00:00 2001 From: Tony Roberts Date: Thu, 10 Apr 2014 13:50:57 +0100 Subject: [PATCH 1/5] Reference the assembly loader in the Main method to stop it being optimized away, and don't reload assemblies once they're already loaded. --- pythonnet/src/console/pythonconsole.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pythonnet/src/console/pythonconsole.cs b/pythonnet/src/console/pythonconsole.cs index 2184c8730..6c54c471e 100644 --- a/pythonnet/src/console/pythonconsole.cs +++ b/pythonnet/src/console/pythonconsole.cs @@ -9,6 +9,7 @@ using System; using System.Reflection; +using System.Collections.Generic; using Python.Runtime; namespace Python.Runtime { @@ -19,6 +20,9 @@ private PythonConsole() {} [STAThread] public static int Main(string[] args) { + // reference the static assemblyLoader to stop it being optimized away + AssemblyLoader a = assemblyLoader; + string [] cmd = Environment.GetCommandLineArgs(); PythonEngine.Initialize(); @@ -31,16 +35,26 @@ public static int Main(string[] args) { // Register a callback function to load embedded assmeblies. // (Python.Runtime.dll is included as a resource) private sealed class AssemblyLoader { + Dictionary loadedAssemblies; + public AssemblyLoader() { + loadedAssemblies = new Dictionary(); + AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { String resourceName = new AssemblyName(args.Name).Name + ".dll"; + if (loadedAssemblies.ContainsKey(resourceName)) { + return loadedAssemblies[resourceName]; + } + // looks for the assembly from the resources and load it using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) { if (stream != null) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); - return Assembly.Load(assemblyData); + Assembly assembly = Assembly.Load(assemblyData); + loadedAssemblies[resourceName] = assembly; + return assembly; } } From 2b11631a5cc9c08b0ff3359d041ee5ade1fc605f Mon Sep 17 00:00:00 2001 From: Tony Roberts Date: Fri, 11 Apr 2014 11:01:37 +0100 Subject: [PATCH 2/5] make sure the GIL is released in ThreadTest --- pythonnet/src/testing/threadtest.cs | 54 +++++++++++++++++------------ 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/pythonnet/src/testing/threadtest.cs b/pythonnet/src/testing/threadtest.cs index a31fd9768..caad9fcf4 100644 --- a/pythonnet/src/testing/threadtest.cs +++ b/pythonnet/src/testing/threadtest.cs @@ -39,35 +39,43 @@ public class ThreadTest { public static string CallEchoString(string arg) { IntPtr gs = PythonEngine.AcquireLock(); - if (module == null) { - module = PythonEngine.ModuleFromString("tt", testmod); + try { + if (module == null) { + module = PythonEngine.ModuleFromString("tt", testmod); + } + PyObject func = module.GetAttr("echostring"); + PyString parg = new PyString(arg); + PyObject temp = func.Invoke(parg); + string result = (string)temp.AsManagedObject(typeof(String)); + func.Dispose(); + parg.Dispose(); + temp.Dispose(); + return result; + } + finally { + PythonEngine.ReleaseLock(gs); } - PyObject func = module.GetAttr("echostring"); - PyString parg = new PyString(arg); - PyObject temp = func.Invoke(parg); - string result = (string)temp.AsManagedObject(typeof(String)); - func.Dispose(); - parg.Dispose(); - temp.Dispose(); - PythonEngine.ReleaseLock(gs); - return result; } public static string CallEchoString2(string arg) { IntPtr gs = PythonEngine.AcquireLock(); - if (module == null) { - module = PythonEngine.ModuleFromString("tt", testmod); - } + try { + if (module == null) { + module = PythonEngine.ModuleFromString("tt", testmod); + } - PyObject func = module.GetAttr("echostring2"); - PyString parg = new PyString(arg); - PyObject temp = func.Invoke(parg); - string result = (string)temp.AsManagedObject(typeof(String)); - func.Dispose(); - parg.Dispose(); - temp.Dispose(); - PythonEngine.ReleaseLock(gs); - return result; + PyObject func = module.GetAttr("echostring2"); + PyString parg = new PyString(arg); + PyObject temp = func.Invoke(parg); + string result = (string)temp.AsManagedObject(typeof(String)); + func.Dispose(); + parg.Dispose(); + temp.Dispose(); + return result; + } + finally { + PythonEngine.ReleaseLock(gs); + } } From dfdcfe7ed082ea3249a4fc72242c39abc9026506 Mon Sep 17 00:00:00 2001 From: Tony Roberts Date: Fri, 11 Apr 2014 11:37:10 +0100 Subject: [PATCH 3/5] Use the assembly short name to find the embedded Python.Runtime (other assemblies may reference it with the full name). --- pythonnet/src/console/pythonconsole.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pythonnet/src/console/pythonconsole.cs b/pythonnet/src/console/pythonconsole.cs index 6c54c471e..26fc756d5 100644 --- a/pythonnet/src/console/pythonconsole.cs +++ b/pythonnet/src/console/pythonconsole.cs @@ -41,7 +41,8 @@ public AssemblyLoader() { loadedAssemblies = new Dictionary(); AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { - String resourceName = new AssemblyName(args.Name).Name + ".dll"; + string shortName = args.Name.Split(',')[0]; + String resourceName = shortName + ".dll"; if (loadedAssemblies.ContainsKey(resourceName)) { return loadedAssemblies[resourceName]; From b65fa30c7b21cce263ed9ada982bd47bc18eea04 Mon Sep 17 00:00:00 2001 From: Tony Roberts Date: Fri, 11 Apr 2014 14:37:19 +0100 Subject: [PATCH 4/5] Use Assembly.Load(Byte[]) instead of Assembly.LoadFrom. --- pythonnet/src/runtime/assemblymanager.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pythonnet/src/runtime/assemblymanager.cs b/pythonnet/src/runtime/assemblymanager.cs index b07cde1c2..291301466 100644 --- a/pythonnet/src/runtime/assemblymanager.cs +++ b/pythonnet/src/runtime/assemblymanager.cs @@ -30,6 +30,7 @@ internal class AssemblyManager { static ResolveEventHandler rhandler; static Dictionary probed; static List assemblies; + static Dictionary loadedAssemblies; internal static List pypath; private AssemblyManager() {} @@ -46,6 +47,7 @@ internal static void Initialize() { probed = new Dictionary(32); //generics = new Dictionary>(); assemblies = new List(16); + loadedAssemblies = new Dictionary(); pypath = new List(16); AppDomain domain = AppDomain.CurrentDomain; @@ -202,7 +204,19 @@ public static Assembly LoadAssemblyPath(string name) { string path = FindAssembly(name); Assembly assembly = null; if (path != null) { - try { assembly = Assembly.LoadFrom(path); } + if (loadedAssemblies.ContainsKey(path)) { + return loadedAssemblies[path]; + } + // Avoid using Assembly.LoadFrom as referenced assemblies that exist + // in the same path will be loaded directly from there, rather than + // using other versions already loaded. This is a problem if there + // is a Python.Runtime.dll in the same folder as the assembly being + // loaded, as that will result in two instances being loaded. + try { + byte[] bytes = System.IO.File.ReadAllBytes(path); + assembly = Assembly.Load(bytes); + loadedAssemblies[path] = assembly; + } catch {} } return assembly; From 56bebfab89f72f0177e93e45a356c944da15327f Mon Sep 17 00:00:00 2001 From: Tony Roberts Date: Fri, 11 Apr 2014 15:09:19 +0100 Subject: [PATCH 5/5] add C:\Python to PATH --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index b20604dce..6bf286fbd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,7 @@ install: - ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:\get-pip.py') # appveyor has python 2.7.6 x86 preinstalled, but in the wrong directory, this works around this - ps: if ($env:pythonurl -eq "http://www.python.org/ftp/python/2.7.6/python-2.7.6.msi") {mi c:\python27 c:\python} + - set PATH=C:\Python;%PATH% - C:\Python\python.exe c:\get-pip.py - C:\Python\Scripts\pip.exe install wheel pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy