diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ae62d692..99b895154 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning][].
This document follows the conventions laid out in [Keep a CHANGELOG][].
## [unreleased][]
+- Added VS 2017 build with net40 and NetStandard 1.5 targets
### Added
- Added `clr.GetClrType` (#432, #433)
diff --git a/pythonnet.15.sln b/pythonnet.15.sln
new file mode 100644
index 000000000..0358a736b
--- /dev/null
+++ b/pythonnet.15.sln
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.10
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Runtime.15", "src\runtime\Python.Runtime.15.csproj", "{4D2089E1-5B6A-4799-984B-178AE467902D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.EmbeddingTest.15", "src\embed_tests\Python.EmbeddingTest.15.csproj", "{4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug-Linux-x64|x64 = Debug-Linux-x64|x64
+ Debug-Win-x64|x64 = Debug-Win-x64|x64
+ Release-Linux-x64|x64 = Release-Linux-x64|x64
+ Release-Win-x64|x64 = Release-Win-x64|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Debug-Linux-x64|x64.ActiveCfg = Debug-Linux-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Debug-Linux-x64|x64.Build.0 = Debug-Linux-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Debug-Win-x64|x64.ActiveCfg = Debug-Win-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Debug-Win-x64|x64.Build.0 = Debug-Win-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Release-Linux-x64|x64.ActiveCfg = Release-Win-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Release-Linux-x64|x64.Build.0 = Release-Win-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Release-Win-x64|x64.ActiveCfg = Release-Win-x64|x64
+ {4D2089E1-5B6A-4799-984B-178AE467902D}.Release-Win-x64|x64.Build.0 = Release-Win-x64|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Debug-Linux-x64|x64.ActiveCfg = Debug|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Debug-Linux-x64|x64.Build.0 = Debug|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Debug-Win-x64|x64.ActiveCfg = Debug|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Debug-Win-x64|x64.Build.0 = Debug|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Release-Linux-x64|x64.ActiveCfg = Release|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Release-Linux-x64|x64.Build.0 = Release|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Release-Win-x64|x64.ActiveCfg = Release|x64
+ {4CACAA81-CC6A-4381-85B8-3A4B57EFE3BD}.Release-Win-x64|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/embed_tests/Program.cs b/src/embed_tests/Program.cs
new file mode 100644
index 000000000..349bf4522
--- /dev/null
+++ b/src/embed_tests/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Reflection;
+using NUnit.Common;
+using NUnitLite;
+
+namespace Python.EmbeddingTest
+{
+ public class Program
+ {
+ public static int Main(string[] args)
+ {
+ ////var example = new TestExample();
+ ////example.SetUp();
+ ////example.TestReadme();
+ ////example.Dispose();
+ ////return 0;
+ return new AutoRun(typeof(Program).GetTypeInfo().Assembly)
+ .Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
+ }
+ }
+}
diff --git a/src/embed_tests/Properties/PublishProfiles/FolderProfile.pubxml b/src/embed_tests/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 000000000..6bdb8c414
--- /dev/null
+++ b/src/embed_tests/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,14 @@
+
+
+
+
+ FileSystem
+ Debug-Linux-x64
+ netcoreapp1.0
+ bin\publish\Debug-Linux-x64
+ ubuntu.14.04-x64
+
+
\ No newline at end of file
diff --git a/src/embed_tests/Properties/launchSettings.json b/src/embed_tests/Properties/launchSettings.json
new file mode 100644
index 000000000..a8841cea2
--- /dev/null
+++ b/src/embed_tests/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "Python.EmbeddingTest.15": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/embed_tests/Python.EmbeddingTest.15.csproj b/src/embed_tests/Python.EmbeddingTest.15.csproj
new file mode 100644
index 000000000..8d4321025
--- /dev/null
+++ b/src/embed_tests/Python.EmbeddingTest.15.csproj
@@ -0,0 +1,64 @@
+
+
+ exe
+ netcoreapp1.0
+ win7-x64;ubuntu.16.04-x64;ubuntu.14.04-x64
+ Python.EmbeddingTest
+ Python.EmbeddingTest
+ Python.EmbeddingTest
+ 3.0.0
+ Alpha
+ false
+ false
+ True
+
+ 1.6.0
+
+ Full
+
+
+ x86
+
+
+ x64
+
+
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);XPLAT
+
+
+
+
+ 3.6.1
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.0.1
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
\ No newline at end of file
diff --git a/src/embed_tests/pyimport.cs b/src/embed_tests/pyimport.cs
index 3bb9a34d6..dbf71da24 100644
--- a/src/embed_tests/pyimport.cs
+++ b/src/embed_tests/pyimport.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using NUnit.Framework;
using Python.Runtime;
@@ -30,7 +30,11 @@ public void SetUp()
/* Append the tests directory to sys.path
* using reflection to circumvent the private
* modifiers placed on most Runtime methods. */
+#if XPLAT
+ const string s = "fixtures";
+#else
const string s = "../fixtures";
+#endif
string testPath = Path.Combine(TestContext.CurrentContext.TestDirectory, s);
IntPtr str = Runtime.Runtime.PyString_FromString(testPath);
diff --git a/src/runtime/Python.Runtime.15.csproj b/src/runtime/Python.Runtime.15.csproj
new file mode 100644
index 000000000..f58a1360e
--- /dev/null
+++ b/src/runtime/Python.Runtime.15.csproj
@@ -0,0 +1,99 @@
+
+
+
+ net40;netstandard1.5
+ Python.Runtime
+ Python.Runtime
+ Python.Runtime
+ 3.0.0
+ Alpha
+ false
+ false
+ True
+
+ 1.6.0
+
+
+ x64
+ TRACE;DEBUG;X64;LINUX;UNIX;UCS4;PYTHON_WITH_PYMALLOC;MONO_LINUX
+
+
+ x64
+ TRACE;DEBUG;X64;LINUX;UNIX;UCS4;PYTHON_WITH_PYMALLOC;MONO_LINUX
+
+
+ x64
+ TRACE;DEBUG;X64;LINUX;UNIX;UCS4;PYTHON_WITH_PYMALLOC;MONO_LINUX
+
+
+ x64
+ TRACE;DEBUG;X64;LINUX;UNIX;UCS4;PYTHON_WITH_PYMALLOC;MONO_LINUX
+
+
+
+ x64
+ TRACE;DEBUG;X64;UCS2
+
+
+ x64
+ TRACE;DEBUG;X64;UCS2
+
+
+ x64
+ TRACE;X64;UCS2
+
+
+ x64
+ TRACE;DEBUG;X64;UCS2;
+
+
+
+ $(DefineConstants);XPLAT;REFLECTIONBRIDGE;PYTHON3;PYTHON35
+
+
+
+
+ bin\Debug
+
+
+
+
+ 2.0.11
+
+
+ 4.0.1
+
+
+ 4.1.0
+
+
+ 4.0.1
+
+
+ 4.0.11
+
+
+ 4.0.1
+
+
+ 4.1.0
+
+
+ 4.0.0
+
+
+ 4.0.0-rc3-24212-01
+
+
+ 4.0.0
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj
index 82825a626..2e614d6d5 100644
--- a/src/runtime/Python.Runtime.csproj
+++ b/src/runtime/Python.Runtime.csproj
@@ -76,6 +76,7 @@
+
Properties\SharedAssemblyInfo.cs
@@ -158,6 +159,9 @@
clr.py
+
+
+
$(TargetPath)
diff --git a/src/runtime/arrayobject.cs b/src/runtime/arrayobject.cs
index a10688749..0c174135c 100644
--- a/src/runtime/arrayobject.cs
+++ b/src/runtime/arrayobject.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
namespace Python.Runtime
@@ -140,8 +140,8 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v)
int rank = items.Rank;
int index;
object value;
-
- if (items.IsReadOnly)
+
+ if (((IList)items).IsReadOnly)
{
Exceptions.RaiseTypeError("array is read-only");
return -1;
diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs
index 06a4449a2..ad287eba8 100644
--- a/src/runtime/assemblymanager.cs
+++ b/src/runtime/assemblymanager.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -6,6 +6,9 @@
using System.IO;
using System.Reflection;
using System.Threading;
+#if NETSTANDARD1_5
+using System.Runtime.Loader;
+#endif
namespace Python.Runtime
{
@@ -19,7 +22,9 @@ internal class AssemblyManager
// therefore this should be a ConcurrentDictionary
private static ConcurrentDictionary> namespaces;
//private static Dictionary> generics;
+#if !NETSTANDARD1_5
private static AssemblyLoadEventHandler lhandler;
+#endif
private static ResolveEventHandler rhandler;
// updated only under GIL?
@@ -48,9 +53,10 @@ internal static void Initialize()
AppDomain domain = AppDomain.CurrentDomain;
+#if !NETSTANDARD1_5
lhandler = new AssemblyLoadEventHandler(AssemblyLoadHandler);
domain.AssemblyLoad += lhandler;
-
+#endif
rhandler = new ResolveEventHandler(ResolveHandler);
domain.AssemblyResolve += rhandler;
@@ -76,11 +82,13 @@ internal static void Initialize()
internal static void Shutdown()
{
AppDomain domain = AppDomain.CurrentDomain;
+#if !NETSTANDARD1_5
domain.AssemblyLoad -= lhandler;
+#endif
domain.AssemblyResolve -= rhandler;
}
-
+#if !NETSTANDARD1_5
///
/// Event handler for assembly load events. At the time the Python
/// runtime loads, we scan the app domain to map the assemblies that
@@ -94,7 +102,7 @@ private static void AssemblyLoadHandler(object ob, AssemblyLoadEventArgs args)
assemblies.Add(assembly);
ScanAssembly(assembly);
}
-
+#endif
///
/// Event handler for assembly resolve events. This is needed because
@@ -196,7 +204,11 @@ public static Assembly LoadAssembly(string name)
Assembly assembly = null;
try
{
+#if NETSTANDARD1_5
+ assembly = Assembly.Load(new AssemblyName(name));
+#else
assembly = Assembly.Load(name);
+#endif
}
catch (Exception)
{
@@ -220,7 +232,11 @@ public static Assembly LoadAssemblyPath(string name)
{
try
{
+#if NETSTANDARD1_5
+ assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
+#else
assembly = Assembly.LoadFrom(path);
+#endif
}
catch (Exception)
{
@@ -247,7 +263,11 @@ public static Assembly LoadAssemblyFullPath(string name)
{
try
{
+#if NETSTANDARD1_5
+ assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(name);
+#else
assembly = Assembly.LoadFrom(name);
+#endif
}
catch (Exception)
{
@@ -364,7 +384,11 @@ internal static void ScanAssembly(Assembly assembly)
namespaces[ns].TryAdd(assembly, string.Empty);
}
+#if !NETSTANDARD1_5
if (ns != null && t.IsGenericTypeDefinition)
+#else
+ if (ns != null && t.GetTypeInfo().IsGenericTypeDefinition)
+#endif
{
GenericUtil.Register(t);
}
diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs
index 4dd3b5364..edbb32061 100644
--- a/src/runtime/classbase.cs
+++ b/src/runtime/classbase.cs
@@ -1,6 +1,7 @@
-using System;
+using System;
using System.Collections;
using System.Runtime.InteropServices;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -25,7 +26,7 @@ internal ClassBase(Type tp)
internal virtual bool CanSubclass()
{
- return !type.IsEnum;
+ return !type.IsEnum();
}
///
diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs
index 16d3b99db..37c99934f 100644
--- a/src/runtime/classderived.cs
+++ b/src/runtime/classderived.cs
@@ -5,6 +5,7 @@
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -123,7 +124,11 @@ internal static Type CreateDerivedType(string name,
if (null == assemblyName)
{
+#if NETSTANDARD1_5
+ assemblyName = Assembly.GetEntryAssembly().FullName;
+#else
assemblyName = Assembly.GetExecutingAssembly().FullName;
+#endif
}
ModuleBuilder moduleBuilder = GetModuleBuilder(assemblyName, moduleName);
@@ -133,7 +138,7 @@ internal static Type CreateDerivedType(string name,
// if the base type is an interface then use System.Object as the base class
// and add the base type to the list of interfaces this new class will implement.
- if (baseType.IsInterface)
+ if (baseType.IsInterface())
{
interfaces.Add(baseType);
baseClass = typeof(object);
@@ -181,7 +186,11 @@ internal static Type CreateDerivedType(string name,
}
// override any virtual methods not already overridden by the properties above
+#if NETSTANDARD1_5
+ MethodInfo[] methods = baseType.GetTypeInfo().GetMethods();
+#else
MethodInfo[] methods = baseType.GetMethods();
+#endif
var virtualMethods = new HashSet();
foreach (MethodInfo method in methods)
{
@@ -249,16 +258,25 @@ internal static Type CreateDerivedType(string name,
il.Emit(OpCodes.Call, baseClass.GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance));
il.Emit(OpCodes.Ret);
+#if NETSTANDARD1_5
+ TypeInfo type = typeBuilder.CreateTypeInfo();
+ // scan the assembly so the newly added class can be imported
+ Assembly assembly = type.Assembly;
+#else
Type type = typeBuilder.CreateType();
-
// scan the assembly so the newly added class can be imported
Assembly assembly = Assembly.GetAssembly(type);
+#endif
AssemblyManager.ScanAssembly(assembly);
// FIXME: assemblyBuilder not used
AssemblyBuilder assemblyBuilder = assemblyBuilders[assemblyName];
+#if NETSTANDARD1_5
+ return type.AsType();
+#else
return type;
+#endif
}
///
@@ -309,7 +327,7 @@ private static void AddConstructor(ConstructorInfo ctor, Type baseType, TypeBuil
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg, i + 1);
- if (parameterTypes[i].IsValueType)
+ if (parameterTypes[i].IsValueType())
{
il.Emit(OpCodes.Box, parameterTypes[i]);
}
@@ -387,7 +405,7 @@ private static void AddVirtualMethod(MethodInfo method, Type baseType, TypeBuild
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg, i + 1);
- if (parameterTypes[i].IsValueType)
+ if (parameterTypes[i].IsValueType())
{
il.Emit(OpCodes.Box, parameterTypes[i]);
}
@@ -474,7 +492,7 @@ private static void AddPythonMethod(string methodName, PyObject func, TypeBuilde
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldarg, i + 1);
- if (argTypes[i].IsValueType)
+ if (argTypes[i].IsValueType())
{
il.Emit(OpCodes.Box, argTypes[i]);
}
@@ -591,8 +609,13 @@ private static ModuleBuilder GetModuleBuilder(string assemblyName, string module
}
else
{
+#if NETSTANDARD1_5
+ assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName),
+ AssemblyBuilderAccess.Run);
+#else
assemblyBuilder = domain.DefineDynamicAssembly(new AssemblyName(assemblyName),
AssemblyBuilderAccess.Run);
+#endif
assemblyBuilders[assemblyName] = assemblyBuilder;
}
@@ -677,12 +700,18 @@ public static T InvokeMethod(IPythonDerivedType obj, string methodName, strin
{
throw new NotImplementedException("Python object does not have a '" + methodName + "' method");
}
-
+#if NETSTANDARD1_5
+ return (T)obj.GetType()
+ .GetTypeInfo()
+ .GetMethod(origMethodName, BindingFlags.InvokeMethod)
+ .Invoke(obj, args);
+#else
return (T)obj.GetType().InvokeMember(origMethodName,
BindingFlags.InvokeMethod,
null,
obj,
args);
+#endif
}
public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, string origMethodName,
@@ -740,11 +769,18 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s
throw new NotImplementedException($"Python object does not have a '{methodName}' method");
}
+#if NETSTANDARD1_5
+ obj.GetType()
+ .GetTypeInfo()
+ .GetMethod(origMethodName, BindingFlags.InvokeMethod)
+ .Invoke(obj, args);
+#else
obj.GetType().InvokeMember(origMethodName,
BindingFlags.InvokeMethod,
null,
obj,
args);
+#endif
}
public static T InvokeGetProperty(IPythonDerivedType obj, string propertyName)
@@ -802,11 +838,17 @@ public static void InvokeSetProperty(IPythonDerivedType obj, string propertyN
public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, object[] args)
{
// call the base constructor
+#if NETSTANDARD1_5
+ obj.GetType()
+ .GetMethod(origCtorName, BindingFlags.InvokeMethod)
+ .Invoke(obj, args);
+#else
obj.GetType().InvokeMember(origCtorName,
BindingFlags.InvokeMethod,
null,
obj,
args);
+#endif
CLRObject self = null;
IntPtr gs = Runtime.PyGILState_Ensure();
diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs
index 6a9d40ebd..58e4037dd 100644
--- a/src/runtime/classmanager.cs
+++ b/src/runtime/classmanager.cs
@@ -1,9 +1,10 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -73,7 +74,11 @@ private static ClassBase CreateClass(Type type)
// lets us check once (vs. on every lookup) in case we need to
// wrap Exception-derived types in old-style classes
+#if NETSTANDARD1_5
+ if (type.GetTypeInfo().ContainsGenericParameters)
+#else
if (type.ContainsGenericParameters)
+#endif
{
impl = new GenericType(type);
}
@@ -88,7 +93,7 @@ private static ClassBase CreateClass(Type type)
impl = new ArrayObject(type);
}
- else if (type.IsInterface)
+ else if (type.IsInterface())
{
impl = new InterfaceObject(type);
}
@@ -236,7 +241,7 @@ private static ClassInfo GetClassInfo(Type type)
}
}
- if (type.IsInterface)
+ if (type.IsInterface())
{
// Interface inheritance seems to be a different animal:
// more contractual, less structural. Thus, a Type that
@@ -358,12 +363,21 @@ private static ClassInfo GetClassInfo(Type type)
continue;
case MemberTypes.NestedType:
+#if NETSTANDARD1_5
+ tp = ((TypeInfo) mi).AsType();
+ if (!(tp.IsNestedPublic() || tp.GetTypeInfo().IsNestedFamily ||
+ tp.GetTypeInfo().IsNestedFamORAssem))
+ {
+ continue;
+ }
+#else
tp = (Type)mi;
if (!(tp.IsNestedPublic || tp.IsNestedFamily ||
tp.IsNestedFamORAssem))
{
continue;
}
+#endif
// Note the given instance might be uninitialized
ob = GetClass(tp);
ci.members[mi.Name] = ob;
diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs
index 46257c73f..a0d383cde 100644
--- a/src/runtime/classobject.cs
+++ b/src/runtime/classobject.cs
@@ -1,5 +1,6 @@
-using System;
+using System;
using System.Reflection;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -65,7 +66,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
// Primitive types do not have constructors, but they look like
// they do from Python. If the ClassObject represents one of the
// convertible primitive types, just convert the arg directly.
- if (type.IsPrimitive || type == typeof(string))
+ if (type.IsPrimitive() || type == typeof(string))
{
if (Runtime.PyTuple_Size(args) != 1)
{
@@ -84,13 +85,13 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
return CLRObject.GetInstHandle(result, tp);
}
- if (type.IsAbstract)
+ if (type.IsAbstract())
{
Exceptions.SetError(Exceptions.TypeError, "cannot instantiate abstract class");
return IntPtr.Zero;
}
- if (type.IsEnum)
+ if (type.IsEnum())
{
Exceptions.SetError(Exceptions.TypeError, "cannot instantiate enumeration");
return IntPtr.Zero;
diff --git a/src/runtime/codegenerator.cs b/src/runtime/codegenerator.cs
index dc466bafb..b0f5784ce 100644
--- a/src/runtime/codegenerator.cs
+++ b/src/runtime/codegenerator.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
@@ -21,7 +21,11 @@ internal CodeGenerator()
var aname = new AssemblyName { Name = "__CodeGenerator_Assembly" };
var aa = AssemblyBuilderAccess.Run;
+#if NETSTANDARD1_5
+ aBuilder = AssemblyBuilder.DefineDynamicAssembly(aname, aa);
+#else
aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
+#endif
mBuilder = aBuilder.DefineDynamicModule("__CodeGenerator_Module");
}
diff --git a/src/runtime/constructorbinder.cs b/src/runtime/constructorbinder.cs
index 1fc541920..59b849950 100644
--- a/src/runtime/constructorbinder.cs
+++ b/src/runtime/constructorbinder.cs
@@ -1,5 +1,6 @@
-using System;
+using System;
using System.Reflection;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -51,8 +52,8 @@ internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info)
{
object result;
- if (_containingType.IsValueType && !_containingType.IsPrimitive &&
- !_containingType.IsEnum && _containingType != typeof(decimal) &&
+ if (_containingType.IsValueType() && !_containingType.IsPrimitive() &&
+ !_containingType.IsEnum() && _containingType != typeof(decimal) &&
Runtime.PyTuple_Size(args) == 0)
{
// If you are trying to construct an instance of a struct by
diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs
index 5179c849b..5b8fbbf92 100644
--- a/src/runtime/converter.cs
+++ b/src/runtime/converter.cs
@@ -1,17 +1,20 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
///
/// Performs data conversions between managed types and Python types.
///
+#if !NETSTANDARD1_5
[SuppressUnmanagedCodeSecurity]
+#endif
internal class Converter
{
private Converter()
@@ -134,7 +137,7 @@ internal static IntPtr ToPython(object value, Type type)
return result;
}
- if (value is IList && value.GetType().IsGenericType)
+ if (value is IList && value.GetType().IsGenericType())
{
using (var resultlist = new PyList())
{
@@ -312,7 +315,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
return false;
}
- if (value == Runtime.PyNone && !obType.IsValueType)
+ if (value == Runtime.PyNone && !obType.IsValueType())
{
result = null;
return true;
@@ -334,7 +337,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
return ToArray(value, obType, out result, setError);
}
- if (obType.IsEnum)
+ if (obType.IsEnum())
{
return ToEnum(value, obType, out result, setError);
}
diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs
index 2a91a74b4..83bacc378 100644
--- a/src/runtime/debughelper.cs
+++ b/src/runtime/debughelper.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -105,8 +105,13 @@ internal static void DumpInst(IntPtr ob)
[Conditional("DEBUG")]
internal static void debug(string msg)
{
+#if NETSTANDARD1_5
+ StackTrace st = new StackTrace(new Exception(msg), true);
+ StackFrame sf = st.GetFrames()[0];
+#else
var st = new StackTrace(1, true);
StackFrame sf = st.GetFrame(0);
+#endif
MethodBase mb = sf.GetMethod();
Type mt = mb.DeclaringType;
string caller = mt.Name + "." + sf.GetMethod().Name;
@@ -116,10 +121,10 @@ internal static void debug(string msg)
Console.WriteLine(" {0}", msg);
}
- ///
+ ///
/// Helper function to inspect/compare managed to native conversions.
- /// Especially useful when debugging CustomMarshaler.
- ///
+ /// Especially useful when debugging CustomMarshaler.
+ ///
///
[Conditional("DEBUG")]
public static void PrintHexBytes(byte[] bytes)
diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs
index df5eec427..2d3c142fd 100644
--- a/src/runtime/delegatemanager.cs
+++ b/src/runtime/delegatemanager.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -118,7 +119,7 @@ private Type GetDispatcher(Type dtype)
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldarg_S, (byte)(c + 1));
- if (t.IsValueType)
+ if (t.IsValueType())
{
il.Emit(OpCodes.Box, t);
}
@@ -135,14 +136,18 @@ private Type GetDispatcher(Type dtype)
{
il.Emit(OpCodes.Pop);
}
- else if (method.ReturnType.IsValueType)
+ else if (method.ReturnType.IsValueType())
{
il.Emit(OpCodes.Unbox_Any, method.ReturnType);
}
il.Emit(OpCodes.Ret);
+#if NETSTANDARD1_5
+ Type disp = tb.CreateTypeInfo().AsType();
+#else
Type disp = tb.CreateType();
+#endif
cache[dtype] = disp;
return disp;
}
@@ -157,7 +162,11 @@ internal Delegate GetDelegate(Type dtype, IntPtr callable)
Type dispatcher = GetDispatcher(dtype);
object[] args = { callable, dtype };
object o = Activator.CreateInstance(dispatcher, args);
+#if NETSTANDARD1_5
+ return DelegateShim.CreateDelegate(dtype, o, "Invoke");
+#else
return Delegate.CreateDelegate(dtype, o, "Invoke");
+#endif
}
}
diff --git a/src/runtime/delegateobject.cs b/src/runtime/delegateobject.cs
index e1103cbc7..608aed25c 100644
--- a/src/runtime/delegateobject.cs
+++ b/src/runtime/delegateobject.cs
@@ -1,5 +1,7 @@
-using System;
-
+using System;
+#if NETSTANDARD1_5
+using System.Reflection;
+#endif
namespace Python.Runtime
{
///
diff --git a/src/runtime/eventobject.cs b/src/runtime/eventobject.cs
index 5f18c4609..033cc82b3 100644
--- a/src/runtime/eventobject.cs
+++ b/src/runtime/eventobject.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Reflection;
@@ -47,7 +47,11 @@ internal bool AddEventHandler(IntPtr target, IntPtr handler)
{
reg = new Hashtable();
}
+#if NETSTANDARD1_5
+ object key = obj ?? info.DeclaringType;
+#else
object key = obj ?? info.ReflectedType;
+#endif
var list = reg[key] as ArrayList;
if (list == null)
{
@@ -60,7 +64,11 @@ internal bool AddEventHandler(IntPtr target, IntPtr handler)
// so we have to get the underlying add method explicitly.
object[] args = { d };
MethodInfo mi = info.GetAddMethod(true);
+#if NETSTANDARD1_5
+ mi.Invoke(obj, args);
+#else
mi.Invoke(obj, BindingFlags.Default, null, args, null);
+#endif
return true;
}
@@ -85,7 +93,11 @@ internal bool RemoveEventHandler(IntPtr target, IntPtr handler)
return false;
}
+#if NETSTANDARD1_5
+ object key = obj ?? info.DeclaringType;
+#else
object key = obj ?? info.ReflectedType;
+#endif
var list = reg[key] as ArrayList;
if (list == null)
@@ -107,7 +119,11 @@ internal bool RemoveEventHandler(IntPtr target, IntPtr handler)
args[0] = item.del;
try
{
+#if NETSTANDARD1_5
+ mi.Invoke(obj, args);
+#else
mi.Invoke(obj, BindingFlags.Default, null, args, null);
+#endif
}
catch
{
diff --git a/src/runtime/genericutil.cs b/src/runtime/genericutil.cs
index 9772d082f..510da0287 100644
--- a/src/runtime/genericutil.cs
+++ b/src/runtime/genericutil.cs
@@ -1,5 +1,6 @@
-using System;
+using System;
using System.Collections.Generic;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs
index bc9ac5eee..291b0ad4c 100644
--- a/src/runtime/importhook.cs
+++ b/src/runtime/importhook.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Runtime.InteropServices;
namespace Python.Runtime
@@ -75,7 +75,10 @@ internal static void Shutdown()
if (Runtime.Py_IsInitialized() != 0)
{
Runtime.XDecref(py_clr_module);
+ // TODO: Very strange behavior under CoreCLR. System.ExecutionEngineException (Crash)
+#if !NETSTANDARD1_5
Runtime.XDecref(root.pyHandle);
+#endif
Runtime.XDecref(py_import);
}
}
diff --git a/src/runtime/interfaceobject.cs b/src/runtime/interfaceobject.cs
index ce1bc9eb0..374ce0cc2 100644
--- a/src/runtime/interfaceobject.cs
+++ b/src/runtime/interfaceobject.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -16,7 +16,12 @@ internal class InterfaceObject : ClassBase
internal InterfaceObject(Type tp) : base(tp)
{
+#if NETSTANDARD1_5
+ CoClassAttribute coclass = (CoClassAttribute)
+ tp.GetTypeInfo().GetCustomAttribute(cc_attr);
+#else
var coclass = (CoClassAttribute)Attribute.GetCustomAttribute(tp, cc_attr);
+#endif
if (coclass != null)
{
ctor = coclass.CoClass.GetConstructor(Type.EmptyTypes);
diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs
index 4ae4b61e0..afc9d018a 100644
--- a/src/runtime/interop.cs
+++ b/src/runtime/interop.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
@@ -342,7 +342,11 @@ static Interop()
// Here we build a mapping of PyTypeObject slot names to the
// appropriate prototype (delegate) type to use for the slot.
+#if NETSTANDARD1_5
+ Type[] items = typeof(Interop).GetTypeInfo().GetNestedTypes();
+#else
Type[] items = typeof(Interop).GetNestedTypes();
+#endif
Hashtable p = new Hashtable();
for (int i = 0; i < items.Length; i++)
@@ -453,14 +457,22 @@ internal static IntPtr GetThunk(MethodInfo method, string funcType = null)
{
Type dt;
if (funcType != null)
+#if NETSTANDARD1_5
+ dt = typeof(Interop).GetTypeInfo().GetNestedType(funcType) as Type;
+#else
dt = typeof(Interop).GetNestedType(funcType) as Type;
+#endif
else
dt = GetPrototype(method.Name);
if (dt != null)
{
IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size);
+#if NETSTANDARD1_5
+ Delegate d = DelegateShim.CreateDelegate(dt, method);
+#else
Delegate d = Delegate.CreateDelegate(dt, method);
+#endif
Thunk cb = new Thunk(d);
Marshal.StructureToPtr(cb, tmp, false);
IntPtr fp = Marshal.ReadIntPtr(tmp, 0);
diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs
index 982f4a632..504a5720b 100644
--- a/src/runtime/metatype.cs
+++ b/src/runtime/metatype.cs
@@ -1,4 +1,7 @@
using System;
+#if NETSTANDARD1_5
+using System.Reflection;
+#endif
using System.Runtime.InteropServices;
namespace Python.Runtime
diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs
index f0c58f34f..fd6fec98b 100644
--- a/src/runtime/methodbinder.cs
+++ b/src/runtime/methodbinder.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Reflection;
@@ -327,7 +327,11 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
}
}
else if (pynargs > clrnargs && clrnargs > 0 &&
- Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute)))
+#if NETSTANDARD1_5
+ pi[clrnargs - 1].IsDefined(typeof(ParamArrayAttribute)))
+#else
+ Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute)))
+#endif
{
// This is a `foo(params object[] bar)` style method
match = true;
@@ -518,7 +522,11 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i
try
{
+#if NETSTANDARD1_5
+ result = binding.info.Invoke(binding.inst, binding.args);
+#else
result = binding.info.Invoke(binding.inst, BindingFlags.Default, null, binding.args, null);
+#endif
}
catch (Exception e)
{
diff --git a/src/runtime/methodwrapper.cs b/src/runtime/methodwrapper.cs
index 2f3ce3ef2..e41c25cd1 100644
--- a/src/runtime/methodwrapper.cs
+++ b/src/runtime/methodwrapper.cs
@@ -1,4 +1,7 @@
-using System;
+using System;
+#if NETSTANDARD1_5
+using System.Reflection;
+#endif
namespace Python.Runtime
{
diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs
index e683026f9..9aeed54a6 100644
--- a/src/runtime/moduleobject.cs
+++ b/src/runtime/moduleobject.cs
@@ -1,8 +1,10 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -108,7 +110,7 @@ public ManagedType GetAttribute(string name, bool guess)
type = AssemblyManager.LookupType(qname);
if (type != null)
{
- if (!type.IsPublic)
+ if (!type.IsPublic())
{
return null;
}
@@ -134,7 +136,7 @@ public ManagedType GetAttribute(string name, bool guess)
type = AssemblyManager.LookupType(qname);
if (type != null)
{
- if (!type.IsPublic)
+ if (!type.IsPublic())
{
return null;
}
@@ -214,8 +216,8 @@ internal void InitializeModuleMembers()
MethodInfo[] methods = type.GetMethods(flags);
foreach (MethodInfo method in methods)
{
- object[] attrs = method.GetCustomAttributes(funcmarker, false);
- object[] forbid = method.GetCustomAttributes(ftmarker, false);
+ object[] attrs = method.GetCustomAttributes(funcmarker, false).ToArray();
+ object[] forbid = method.GetCustomAttributes(ftmarker, false).ToArray();
bool allow_threads = forbid.Length == 0;
if (attrs.Length > 0)
{
@@ -230,7 +232,7 @@ internal void InitializeModuleMembers()
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
- object[] attrs = property.GetCustomAttributes(propmarker, false);
+ object[] attrs = property.GetCustomAttributes(propmarker, false).ToArray();
if (attrs.Length > 0)
{
string name = property.Name;
@@ -238,7 +240,7 @@ internal void InitializeModuleMembers()
StoreAttribute(name, p);
}
}
- type = type.BaseType;
+ type = type.BaseType();
}
}
diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs
index 9d1b0f41c..9cd428179 100644
--- a/src/runtime/nativecall.cs
+++ b/src/runtime/nativecall.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
@@ -39,8 +39,11 @@ static NativeCall()
var aname = new AssemblyName { Name = "e__NativeCall_Assembly" };
var aa = AssemblyBuilderAccess.Run;
-
+#if NETSTANDARD1_5
+ aBuilder = AssemblyBuilder.DefineDynamicAssembly(aname, aa);
+#else
aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
+#endif
mBuilder = aBuilder.DefineDynamicModule("e__NativeCall_Module");
var ta = TypeAttributes.Public;
@@ -57,7 +60,11 @@ static NativeCall()
GenerateThunk(tBuilder, method);
}
+#if NETSTANDARD1_5
+ Type theType = tBuilder.CreateTypeInfo().AsType();
+#else
Type theType = tBuilder.CreateType();
+#endif
Impl = (INativeCall)Activator.CreateInstance(theType);
}
@@ -106,12 +113,19 @@ private static void GenerateThunk(TypeBuilder tb, MethodInfo method)
il.Emit(OpCodes.Ldarg_1);
+#if NETSTANDARD1_5
+ il.EmitCalli(OpCodes.Calli,
+ CallingConventions.ExplicitThis,
+ method.ReturnType,
+ nargs, null
+ );
+#else
il.EmitCalli(OpCodes.Calli,
CallingConvention.Cdecl,
method.ReturnType,
nargs
);
-
+#endif
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(mb, method);
diff --git a/src/runtime/polyfill/DelegateShim.cs b/src/runtime/polyfill/DelegateShim.cs
new file mode 100644
index 000000000..0fcbcbd52
--- /dev/null
+++ b/src/runtime/polyfill/DelegateShim.cs
@@ -0,0 +1,32 @@
+#if NETSTANDARD1_5
+namespace Python.Runtime
+{
+ using System;
+ using System.Linq;
+ using System.Reflection;
+
+ public static class DelegateShim
+ {
+ public static Delegate CreateDelegate(Type dtype, object obj, string methodName)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ var methods = obj.GetType().GetTypeInfo().GetMember(methodName, BindingFlags.Default);
+ if (!methods.Any())
+ {
+ throw new InvalidOperationException("Method does not exist");
+ }
+
+ return CreateDelegate(dtype, (MethodInfo)methods[0]);
+ }
+
+ internal static Delegate CreateDelegate(Type dtype, MethodInfo method)
+ {
+ return method.CreateDelegate(dtype);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/runtime/polyfill/ICustomMarshaler.cs b/src/runtime/polyfill/ICustomMarshaler.cs
new file mode 100644
index 000000000..0b295a6de
--- /dev/null
+++ b/src/runtime/polyfill/ICustomMarshaler.cs
@@ -0,0 +1,34 @@
+// This is copy from https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This the base interface that must be implemented by all custom
+** marshalers.
+**
+**
+=============================================================================*/
+
+#if NETSTANDARD1_5
+using System;
+namespace System.Runtime.InteropServices
+{
+ public interface ICustomMarshaler
+ {
+ Object MarshalNativeToManaged(IntPtr pNativeData);
+
+ IntPtr MarshalManagedToNative(Object ManagedObj);
+
+ void CleanUpNativeData(IntPtr pNativeData);
+
+ void CleanUpManagedData(Object ManagedObj);
+
+ int GetNativeDataSize();
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/runtime/polyfill/ReflectionBridge/LICENSE.txt b/src/runtime/polyfill/ReflectionBridge/LICENSE.txt
new file mode 100644
index 000000000..9bb94287b
--- /dev/null
+++ b/src/runtime/polyfill/ReflectionBridge/LICENSE.txt
@@ -0,0 +1,22 @@
+
+MIT License
+
+Copyright (c) 2016 to 2099 Stef Heyenrath
+
+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.
\ No newline at end of file
diff --git a/src/runtime/polyfill/ReflectionBridge/ReflectionBridgeExtensions.cs b/src/runtime/polyfill/ReflectionBridge/ReflectionBridgeExtensions.cs
new file mode 100644
index 000000000..c421408ac
--- /dev/null
+++ b/src/runtime/polyfill/ReflectionBridge/ReflectionBridgeExtensions.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Reflection;
+
+#if REFLECTIONBRIDGE
+using System.Collections.Generic;
+using System.Linq;
+#endif
+
+namespace ReflectionBridge.Extensions
+{
+ public static class ReflectionBridgeExtensions
+ {
+ public static Assembly GetAssembly(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().Assembly;
+#else
+ return type.Assembly;
+#endif
+ }
+
+ public static bool IsSealed(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsSealed;
+#else
+ return type.IsSealed;
+#endif
+ }
+
+ public static bool IsAbstract(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsAbstract;
+#else
+ return type.IsAbstract;
+#endif
+ }
+
+ public static bool IsEnum(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsEnum;
+#else
+ return type.IsEnum;
+#endif
+ }
+
+ public static bool IsClass(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsClass;
+#else
+ return type.IsClass;
+#endif
+ }
+
+ public static bool IsPrimitive(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsPrimitive;
+#else
+ return type.IsPrimitive;
+#endif
+ }
+
+ public static bool IsPublic(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsPublic;
+#else
+ return type.IsPublic;
+#endif
+ }
+
+ public static bool IsNestedPublic(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsNestedPublic;
+#else
+ return type.IsNestedPublic;
+#endif
+ }
+
+ public static bool IsFromLocalAssembly(this Type type)
+ {
+#if SILVERLIGHT
+ string assemblyName = type.GetAssembly().FullName;
+#else
+ string assemblyName = type.GetAssembly().GetName().Name;
+#endif
+
+ try
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ Assembly.Load(new AssemblyName { Name = assemblyName });
+#else
+ Assembly.Load(assemblyName);
+#endif
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ public static bool IsGenericType(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsGenericType;
+#else
+ return type.IsGenericType;
+#endif
+ }
+
+ public static bool IsInterface(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsInterface;
+#else
+ return type.IsInterface;
+#endif
+ }
+
+ public static Type BaseType(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().BaseType;
+#else
+ return type.BaseType;
+#endif
+ }
+
+ public static bool IsValueType(this Type type)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ return type.GetTypeInfo().IsValueType;
+#else
+ return type.IsValueType;
+#endif
+ }
+
+ public static T GetPropertyValue(this Type type, string propertyName, object target)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ PropertyInfo property = type.GetTypeInfo().GetDeclaredProperty(propertyName);
+ return (T)property.GetValue(target);
+#else
+ return (T)type.InvokeMember(propertyName, BindingFlags.GetProperty, null, target, null);
+#endif
+ }
+
+ public static void SetPropertyValue(this Type type, string propertyName, object target, object value)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ PropertyInfo property = type.GetTypeInfo().GetDeclaredProperty(propertyName);
+ property.SetValue(target, value);
+#else
+ type.InvokeMember(propertyName, BindingFlags.SetProperty, null, target, new object[] { value });
+#endif
+ }
+
+ public static void SetFieldValue(this Type type, string fieldName, object target, object value)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ FieldInfo field = type.GetTypeInfo().GetDeclaredField(fieldName);
+ if (field != null)
+ {
+ field.SetValue(target, value);
+ }
+ else
+ {
+ type.SetPropertyValue(fieldName, target, value);
+ }
+#else
+ type.InvokeMember(fieldName, BindingFlags.SetField | BindingFlags.SetProperty, null, target, new object[] { value });
+#endif
+ }
+
+ public static void InvokeMethod(this Type type, string methodName, object target, T value)
+ {
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ MethodInfo method = type.GetTypeInfo().GetDeclaredMethod(methodName);
+ method.Invoke(target, new object[] { value });
+#else
+ type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, target, new object[] { value });
+#endif
+ }
+
+#if REFLECTIONBRIDGE && (!(NET40 || NET35 || NET20 || SILVERLIGHT))
+ public static IEnumerable GetMethods(this Type someType)
+ {
+ var t = someType;
+ while (t != null)
+ {
+ var ti = t.GetTypeInfo();
+ foreach (var m in ti.DeclaredMethods)
+ yield return m;
+ t = ti.BaseType;
+ }
+ }
+
+ public static Type[] GetGenericArguments(this Type type)
+ {
+ return type.GetTypeInfo().GenericTypeArguments;
+ }
+
+ /*
+ public static bool IsAssignableFrom(this Type type, Type otherType)
+ {
+ return type.GetTypeInfo().IsAssignableFrom(otherType.GetTypeInfo());
+ }*/
+
+ public static bool IsSubclassOf(this Type type, Type c)
+ {
+ return type.GetTypeInfo().IsSubclassOf(c);
+ }
+
+ public static Attribute[] GetCustomAttributes(this Type type)
+ {
+ return type.GetTypeInfo().GetCustomAttributes().ToArray();
+ }
+
+ public static Attribute[] GetCustomAttributes(this Type type, Type attributeType, bool inherit)
+ {
+ return type.GetTypeInfo().GetCustomAttributes(attributeType, inherit).Cast().ToArray();
+ }
+#endif
+ }
+}
\ No newline at end of file
diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs
index f2c97f163..5c76964a7 100644
--- a/src/runtime/propertyobject.cs
+++ b/src/runtime/propertyobject.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Reflection;
+#if !NETSTANDARD1_5
using System.Security.Permissions;
-
+#endif
namespace Python.Runtime
{
///
@@ -12,8 +13,9 @@ internal class PropertyObject : ExtensionType
private PropertyInfo info;
private MethodInfo getter;
private MethodInfo setter;
-
+#if !NETSTANDARD1_5
[StrongNameIdentityPermission(SecurityAction.Assert)]
+#endif
public PropertyObject(PropertyInfo md)
{
getter = md.GetGetMethod(true);
diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs
index 556da698f..a6caf0c93 100644
--- a/src/runtime/pythonengine.cs
+++ b/src/runtime/pythonengine.cs
@@ -193,8 +193,16 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true)
IntPtr builtins = Runtime.PyEval_GetBuiltins();
Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins);
+#if NETSTANDARD1_5
+ Assembly assembly = typeof(Runtime).GetTypeInfo().Assembly;
+#else
Assembly assembly = Assembly.GetExecutingAssembly();
+#endif
+#if XPLAT
+ using (Stream stream = assembly.GetManifestResourceStream("Python.Runtime.resources.clr.py"))
+#else
using (Stream stream = assembly.GetManifestResourceStream("clr.py"))
+#endif
using (var reader = new StreamReader(stream))
{
// add the contents of clr.py to the module
diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs
index 8f730a855..b471fa2c1 100644
--- a/src/runtime/runtime.cs
+++ b/src/runtime/runtime.cs
@@ -2,10 +2,13 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
+#if !NETSTANDARD1_5
[SuppressUnmanagedCodeSecurity]
+#endif
internal static class NativeMethods
{
#if MONO_LINUX || MONO_OSX
@@ -21,7 +24,11 @@ internal static class NativeMethods
public static IntPtr LoadLibrary(string fileName)
{
+#if NETSTANDARD1_5
+ return dlopen(fileName, RTLD_NOW);
+#else
return dlopen(fileName, RTLD_NOW | RTLD_SHARED);
+#endif
}
public static void FreeLibrary(IntPtr handle)
@@ -300,9 +307,13 @@ internal static void Initialize()
IntPtr dllLocal = IntPtr.Zero;
if (_PythonDll != "__Internal")
{
+#if !NETSTANDARD1_5
dllLocal = NativeMethods.LoadLibrary(_PythonDll);
+#endif
}
+#if !NETSTANDARD1_5
_PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dllLocal, "_PyObject_NextNotImplemented");
+#endif
#if !(MONO_LINUX || MONO_OSX)
if (dllLocal != IntPtr.Zero)
{
@@ -318,7 +329,11 @@ internal static void Initialize()
// Need to add the runtime directory to sys.path so that we
// can find built-in assemblies like System.Data, et. al.
+#if NETSTANDARD1_5
+ string rtdir = typeof(string).GetAssembly().Location;
+#else
string rtdir = RuntimeEnvironment.GetRuntimeDirectory();
+#endif
IntPtr path = PySys_GetObject("path");
IntPtr item = PyString_FromString(rtdir);
PyList_Append(path, item);
@@ -623,11 +638,35 @@ internal static unsafe long Refcount(IntPtr op)
internal static extern IntPtr PyGILState_GetThisThreadState();
#if PYTHON3
+#if NETSTANDARD1_5
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ private static extern int Py_Main(
+ int argc,
+ IntPtr argv
+ );
+
+ public static int Py_Main(
+ int argc,
+ string[] argv
+ )
+ {
+ var marshaler = StrArrayMarshaler.GetInstance(string.Empty);
+ var unmanagedDataPtr = marshaler.MarshalManagedToNative(argv);
+
+ int result = Py_Main(argc, unmanagedDataPtr);
+ if (unmanagedDataPtr != IntPtr.Zero)
+ {
+ marshaler.CleanUpNativeData(unmanagedDataPtr);
+ }
+ return result;
+ }
+#else
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Py_Main(
int argc,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv
);
+#endif
#elif PYTHON2
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Py_Main(int argc, string[] argv);
@@ -1183,12 +1222,38 @@ internal static IntPtr PyBytes_AS_STRING(IntPtr ob)
return ob + BytesOffset.ob_sval;
}
+#if NETSTANDARD1_5
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl,
+ EntryPoint = "PyUnicode_FromStringAndSize")]
+ private static extern IntPtr PyString_FromStringAndSize(
+ IntPtr value,
+ int size
+ );
+
+ internal static IntPtr PyString_FromStringAndSize(
+ string value,
+ int size
+ )
+ {
+ var marshaler = Utf8Marshaler.GetInstance(string.Empty);
+ var unmanagedDataPtr = marshaler.MarshalManagedToNative(value);
+
+ IntPtr result = PyString_FromStringAndSize(unmanagedDataPtr, size);
+
+ if (unmanagedDataPtr != IntPtr.Zero)
+ {
+ marshaler.CleanUpNativeData(unmanagedDataPtr);
+ }
+ return result;
+ }
+#else
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl,
EntryPoint = "PyUnicode_FromStringAndSize")]
internal static extern IntPtr PyString_FromStringAndSize(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value,
int size
);
+#endif
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyUnicode_FromStringAndSize(IntPtr value, int size);
@@ -1215,12 +1280,40 @@ internal static bool PyUnicode_Check(IntPtr ob)
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err);
+#if NETSTANDARD1_5
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr PyUnicode_FromKindAndData(
+ int kind,
+ IntPtr s,
+ int size
+ );
+
+ internal static IntPtr PyUnicode_FromKindAndData(
+ int kind,
+ string s,
+ int size
+ )
+ {
+ var marshaler = UcsMarshaler.GetInstance(string.Empty);
+ var unmanagedDataPtr = marshaler.MarshalManagedToNative(s);
+
+ IntPtr result = PyUnicode_FromKindAndData(kind, unmanagedDataPtr, size);
+
+ if (unmanagedDataPtr != IntPtr.Zero)
+ {
+ marshaler.CleanUpNativeData(unmanagedDataPtr);
+ }
+
+ return result;
+ }
+#else
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyUnicode_FromKindAndData(
int kind,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s,
int size
);
+#endif
internal static IntPtr PyUnicode_FromUnicode(string s, int size)
{
@@ -1244,12 +1337,38 @@ internal static IntPtr PyUnicode_FromUnicode(string s, int size)
EntryPoint = PyUnicodeEntryPoint + "FromEncodedObject")]
internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err);
+#if NETSTANDARD1_5
+ [DllImport(_PythonDll, EntryPoint = PyUnicodeEntryPoint + "FromUnicode",
+ CallingConvention = CallingConvention.Cdecl)]
+ private static extern IntPtr PyUnicode_FromUnicode(
+ IntPtr s,
+ int size
+ );
+
+ internal static IntPtr PyUnicode_FromUnicode(
+ string s,
+ int size
+ )
+ {
+ var marshaler = UcsMarshaler.GetInstance(string.Empty);
+ var unmanagedDataPtr = marshaler.MarshalManagedToNative(s);
+
+ IntPtr result = PyUnicode_FromUnicode(unmanagedDataPtr, size);
+ if (unmanagedDataPtr != IntPtr.Zero)
+ {
+ marshaler.CleanUpNativeData(unmanagedDataPtr);
+ }
+
+ return result;
+ }
+#else
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl,
EntryPoint = PyUnicodeEntryPoint + "FromUnicode")]
internal static extern IntPtr PyUnicode_FromUnicode(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s,
int size
);
+#endif
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl,
EntryPoint = PyUnicodeEntryPoint + "GetSize")]
@@ -1438,6 +1557,10 @@ internal static bool PyTuple_Check(IntPtr ob)
// Python iterator API
//====================================================================
+#if PYTHON2
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern bool PyIter_Check(IntPtr pointer);
+#elif PYTHON3
internal static bool PyIter_Check(IntPtr pointer)
{
var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type);
@@ -1491,12 +1614,37 @@ internal static bool PyIter_Check(IntPtr pointer)
internal static extern IntPtr PyImport_GetModuleDict();
#if PYTHON3
+#if NETSTANDARD1_5
+ [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
+ private static extern void PySys_SetArgvEx(
+ int argc,
+ IntPtr argv,
+ int updatepath
+ );
+
+ internal static void PySys_SetArgvEx(
+ int argc,
+ string[] argv,
+ int updatepath
+ )
+ {
+ var marshaler = StrArrayMarshaler.GetInstance(string.Empty);
+ var unmanagedDataPtr = marshaler.MarshalManagedToNative(argv);
+
+ PySys_SetArgvEx(argc, unmanagedDataPtr, updatepath);
+ if (unmanagedDataPtr != IntPtr.Zero)
+ {
+ marshaler.CleanUpNativeData(unmanagedDataPtr);
+ }
+ }
+#else
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern void PySys_SetArgvEx(
int argc,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv,
int updatepath
);
+#endif
#elif PYTHON2
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern void PySys_SetArgvEx(
diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs
index 6570ee083..64d4419b8 100644
--- a/src/runtime/typemanager.cs
+++ b/src/runtime/typemanager.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
+using ReflectionBridge.Extensions;
namespace Python.Runtime
{
@@ -132,9 +134,9 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
{
base_ = Exceptions.Exception;
}
- else if (clrType.BaseType != null)
+ else if (clrType.BaseType() != null)
{
- ClassBase bc = ClassManager.GetClass(clrType.BaseType);
+ ClassBase bc = ClassManager.GetClass(clrType.BaseType());
base_ = bc.pyHandle;
}
@@ -487,7 +489,7 @@ internal static void InitializeSlots(IntPtr type, Type impl)
seen[name] = 1;
}
- impl = impl.BaseType;
+ impl = impl.BaseType();
}
}
@@ -512,7 +514,7 @@ private static void InitMethods(IntPtr pytype, Type type)
{
if (!addedMethods.Contains(method.Name))
{
- object[] attrs = method.GetCustomAttributes(marker, false);
+ object[] attrs = method.GetCustomAttributes(marker, false).ToArray();
if (attrs.Length > 0)
{
string method_name = method.Name;
@@ -524,7 +526,7 @@ private static void InitMethods(IntPtr pytype, Type type)
}
}
}
- type = type.BaseType;
+ type = type.BaseType();
}
}
diff --git a/src/runtime/typemethod.cs b/src/runtime/typemethod.cs
index 4da92613c..757945d7f 100644
--- a/src/runtime/typemethod.cs
+++ b/src/runtime/typemethod.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
namespace Python.Runtime
@@ -33,7 +33,11 @@ public override IntPtr Invoke(IntPtr ob, IntPtr args, IntPtr kw)
{
inst = GetManagedObject(ob);
}
+#if NETSTANDARD1_5
+ return (IntPtr)mi.Invoke(inst, arglist);
+#else
return (IntPtr)mi.Invoke(inst, BindingFlags.Default, null, arglist, null);
+#endif
}
catch (Exception e)
{