Skip to content

Commit fba7586

Browse files
committed
Merge pull request pythonnet#41 from tonyroberts/develop
merge changes to get npython working again on windows fixes pythonnet#39
2 parents 0ac66b3 + 56bebfa commit fba7586

File tree

4 files changed

+64
-26
lines changed

4 files changed

+64
-26
lines changed

appveyor.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ install:
1616
- ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:\get-pip.py')
1717
# appveyor has python 2.7.6 x86 preinstalled, but in the wrong directory, this works around this
1818
- ps: if ($env:pythonurl -eq "http://www.python.org/ftp/python/2.7.6/python-2.7.6.msi") {mi c:\python27 c:\python}
19+
- set PATH=C:\Python;%PATH%
1920
- C:\Python\python.exe c:\get-pip.py
2021
- C:\Python\Scripts\pip.exe install wheel
2122

pythonnet/src/console/pythonconsole.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
using System;
1111
using System.Reflection;
12+
using System.Collections.Generic;
1213
using Python.Runtime;
1314

1415
namespace Python.Runtime {
@@ -19,6 +20,9 @@ private PythonConsole() {}
1920

2021
[STAThread]
2122
public static int Main(string[] args) {
23+
// reference the static assemblyLoader to stop it being optimized away
24+
AssemblyLoader a = assemblyLoader;
25+
2226
string [] cmd = Environment.GetCommandLineArgs();
2327
PythonEngine.Initialize();
2428

@@ -31,16 +35,27 @@ public static int Main(string[] args) {
3135
// Register a callback function to load embedded assmeblies.
3236
// (Python.Runtime.dll is included as a resource)
3337
private sealed class AssemblyLoader {
38+
Dictionary<string, Assembly> loadedAssemblies;
39+
3440
public AssemblyLoader() {
41+
loadedAssemblies = new Dictionary<string, Assembly>();
42+
3543
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
36-
String resourceName = new AssemblyName(args.Name).Name + ".dll";
44+
string shortName = args.Name.Split(',')[0];
45+
String resourceName = shortName + ".dll";
46+
47+
if (loadedAssemblies.ContainsKey(resourceName)) {
48+
return loadedAssemblies[resourceName];
49+
}
3750

3851
// looks for the assembly from the resources and load it
3952
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
4053
if (stream != null) {
4154
Byte[] assemblyData = new Byte[stream.Length];
4255
stream.Read(assemblyData, 0, assemblyData.Length);
43-
return Assembly.Load(assemblyData);
56+
Assembly assembly = Assembly.Load(assemblyData);
57+
loadedAssemblies[resourceName] = assembly;
58+
return assembly;
4459
}
4560
}
4661

pythonnet/src/runtime/assemblymanager.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ internal class AssemblyManager {
3030
static ResolveEventHandler rhandler;
3131
static Dictionary<string, int> probed;
3232
static List<Assembly> assemblies;
33+
static Dictionary<string, Assembly> loadedAssemblies;
3334
internal static List<string> pypath;
3435

3536
private AssemblyManager() {}
@@ -46,6 +47,7 @@ internal static void Initialize() {
4647
probed = new Dictionary<string, int>(32);
4748
//generics = new Dictionary<string, Dictionary<string, string>>();
4849
assemblies = new List<Assembly>(16);
50+
loadedAssemblies = new Dictionary<string, Assembly>();
4951
pypath = new List<string>(16);
5052

5153
AppDomain domain = AppDomain.CurrentDomain;
@@ -202,7 +204,19 @@ public static Assembly LoadAssemblyPath(string name) {
202204
string path = FindAssembly(name);
203205
Assembly assembly = null;
204206
if (path != null) {
205-
try { assembly = Assembly.LoadFrom(path); }
207+
if (loadedAssemblies.ContainsKey(path)) {
208+
return loadedAssemblies[path];
209+
}
210+
// Avoid using Assembly.LoadFrom as referenced assemblies that exist
211+
// in the same path will be loaded directly from there, rather than
212+
// using other versions already loaded. This is a problem if there
213+
// is a Python.Runtime.dll in the same folder as the assembly being
214+
// loaded, as that will result in two instances being loaded.
215+
try {
216+
byte[] bytes = System.IO.File.ReadAllBytes(path);
217+
assembly = Assembly.Load(bytes);
218+
loadedAssemblies[path] = assembly;
219+
}
206220
catch {}
207221
}
208222
return assembly;

pythonnet/src/testing/threadtest.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,35 +39,43 @@ public class ThreadTest {
3939

4040
public static string CallEchoString(string arg) {
4141
IntPtr gs = PythonEngine.AcquireLock();
42-
if (module == null) {
43-
module = PythonEngine.ModuleFromString("tt", testmod);
42+
try {
43+
if (module == null) {
44+
module = PythonEngine.ModuleFromString("tt", testmod);
45+
}
46+
PyObject func = module.GetAttr("echostring");
47+
PyString parg = new PyString(arg);
48+
PyObject temp = func.Invoke(parg);
49+
string result = (string)temp.AsManagedObject(typeof(String));
50+
func.Dispose();
51+
parg.Dispose();
52+
temp.Dispose();
53+
return result;
54+
}
55+
finally {
56+
PythonEngine.ReleaseLock(gs);
4457
}
45-
PyObject func = module.GetAttr("echostring");
46-
PyString parg = new PyString(arg);
47-
PyObject temp = func.Invoke(parg);
48-
string result = (string)temp.AsManagedObject(typeof(String));
49-
func.Dispose();
50-
parg.Dispose();
51-
temp.Dispose();
52-
PythonEngine.ReleaseLock(gs);
53-
return result;
5458
}
5559

5660
public static string CallEchoString2(string arg) {
5761
IntPtr gs = PythonEngine.AcquireLock();
58-
if (module == null) {
59-
module = PythonEngine.ModuleFromString("tt", testmod);
60-
}
62+
try {
63+
if (module == null) {
64+
module = PythonEngine.ModuleFromString("tt", testmod);
65+
}
6166

62-
PyObject func = module.GetAttr("echostring2");
63-
PyString parg = new PyString(arg);
64-
PyObject temp = func.Invoke(parg);
65-
string result = (string)temp.AsManagedObject(typeof(String));
66-
func.Dispose();
67-
parg.Dispose();
68-
temp.Dispose();
69-
PythonEngine.ReleaseLock(gs);
70-
return result;
67+
PyObject func = module.GetAttr("echostring2");
68+
PyString parg = new PyString(arg);
69+
PyObject temp = func.Invoke(parg);
70+
string result = (string)temp.AsManagedObject(typeof(String));
71+
func.Dispose();
72+
parg.Dispose();
73+
temp.Dispose();
74+
return result;
75+
}
76+
finally {
77+
PythonEngine.ReleaseLock(gs);
78+
}
7179
}
7280

7381

0 commit comments

Comments
 (0)
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