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 diff --git a/pythonnet/src/console/pythonconsole.cs b/pythonnet/src/console/pythonconsole.cs index 2184c8730..26fc756d5 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,27 @@ 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"; + string shortName = args.Name.Split(',')[0]; + String resourceName = shortName + ".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; } } 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; 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); + } } 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