Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Make NETSTANDARD the default
Drops also
- Custom XDecref/XIncref (should be readded)
- Remote object handling for .NET Framework
  • Loading branch information
filmor committed Dec 15, 2019
commit f27d7be072d1aebdb6658d91fef03dcc55985b41
38 changes: 31 additions & 7 deletions Python.Runtime/codegenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,40 @@ namespace Python.Runtime
/// </summary>
internal class CodeGenerator
{
private AssemblyBuilder aBuilder;
private ModuleBuilder mBuilder;
private AssemblyBuilder _aBuilder = null;

internal CodeGenerator()
private AssemblyBuilder aBuilder
{
get
{
if (_aBuilder == null)
{
var aname = new AssemblyName { Name = "__CodeGenerator_Assembly" };
var aa = AssemblyBuilderAccess.Run;

_aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
}

return _aBuilder;
}
}

private ModuleBuilder _mBuilder = null;
private ModuleBuilder mBuilder
{
var aname = new AssemblyName { Name = "__CodeGenerator_Assembly" };
var aa = AssemblyBuilderAccess.Run;
get
{
if (_mBuilder == null)
{
_mBuilder = aBuilder.DefineDynamicModule("__CodeGenerator_Module");
}

return _mBuilder;
}
}

aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
mBuilder = aBuilder.DefineDynamicModule("__CodeGenerator_Module");
internal CodeGenerator()
{
}

/// <summary>
Expand Down
8 changes: 0 additions & 8 deletions Python.Runtime/converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,7 @@ internal static IntPtr ToPython(object value, Type type)
var pyderived = value as IPythonDerivedType;
if (null != pyderived)
{
#if NETSTANDARD
return ClassDerivedObject.ToPython(pyderived);
#else
// if object is remote don't do this
if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(pyderived))
{
return ClassDerivedObject.ToPython(pyderived);
}
#endif
}

// hmm - from Python, we almost never care what the declared
Expand Down
128 changes: 0 additions & 128 deletions Python.Runtime/nativecall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace Python.Runtime
/// </summary>
internal class NativeCall
{
#if NETSTANDARD
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Void_1_Delegate(IntPtr a1);

Expand All @@ -48,132 +47,5 @@ public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3)
var d = Marshal.GetDelegateForFunctionPointer<Interop.ObjObjArgFunc>(fp);
return d(a1, a2, a3);
}
#else
private static AssemblyBuilder aBuilder;
private static ModuleBuilder mBuilder;

public static INativeCall Impl;

static NativeCall()
{
// The static constructor is responsible for generating the
// assembly and the methods that implement the IJW thunks.
//
// To do this, we actually use reflection on the INativeCall
// interface (defined below) and generate the required thunk
// code based on the method signatures.

var aname = new AssemblyName { Name = "e__NativeCall_Assembly" };
var aa = AssemblyBuilderAccess.Run;

aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
mBuilder = aBuilder.DefineDynamicModule("e__NativeCall_Module");

var ta = TypeAttributes.Public;
TypeBuilder tBuilder = mBuilder.DefineType("e__NativeCall", ta);

Type iType = typeof(INativeCall);
tBuilder.AddInterfaceImplementation(iType);

// Use reflection to loop over the INativeCall interface methods,
// calling GenerateThunk to create a managed thunk for each one.

foreach (MethodInfo method in iType.GetMethods())
{
GenerateThunk(tBuilder, method);
}

Type theType = tBuilder.CreateType();

Impl = (INativeCall)Activator.CreateInstance(theType);
}

private static void GenerateThunk(TypeBuilder tb, MethodInfo method)
{
ParameterInfo[] pi = method.GetParameters();
int count = pi.Length;
int argc = count - 1;

var args = new Type[count];
for (var i = 0; i < count; i++)
{
args[i] = pi[i].ParameterType;
}

MethodBuilder mb = tb.DefineMethod(
method.Name,
MethodAttributes.Public |
MethodAttributes.Virtual,
method.ReturnType,
args
);

// Build the method signature for the actual native function.
// This is essentially the signature of the wrapper method
// minus the first argument (the passed in function pointer).

var nargs = new Type[argc];
for (var i = 1; i < count; i++)
{
nargs[i - 1] = args[i];
}

// IL generation: the (implicit) first argument of the method
// is the 'this' pointer and the second is the function pointer.
// This code pushes the real args onto the stack, followed by
// the function pointer, then the calli opcode to make the call.

ILGenerator il = mb.GetILGenerator();

for (var i = 0; i < argc; i++)
{
il.Emit(OpCodes.Ldarg_S, i + 2);
}

il.Emit(OpCodes.Ldarg_1);

il.EmitCalli(OpCodes.Calli,
CallingConvention.Cdecl,
method.ReturnType,
nargs
);

il.Emit(OpCodes.Ret);

tb.DefineMethodOverride(mb, method);
}


public static void Void_Call_1(IntPtr fp, IntPtr a1)
{
Impl.Void_Call_1(fp, a1);
}

public static IntPtr Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3)
{
return Impl.Call_3(fp, a1, a2, a3);
}

public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3)
{
return Impl.Int_Call_3(fp, a1, a2, a3);
}
#endif
}

#if !NETSTANDARD
/// <summary>
/// Defines native call signatures to be generated by NativeCall.
/// </summary>
public interface INativeCall
{
void Void_Call_0(IntPtr funcPtr);

void Void_Call_1(IntPtr funcPtr, IntPtr arg1);

int Int_Call_3(IntPtr funcPtr, IntPtr t, IntPtr n, IntPtr v);

IntPtr Call_3(IntPtr funcPtr, IntPtr a1, IntPtr a2, IntPtr a3);
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

namespace Python.Runtime
{
#if NETSTANDARD
public static class ReflectionPolifills
public static class ReflectionPolyfills
{
public static AssemblyBuilder DefineDynamicAssembly(this AppDomain appDomain, AssemblyName assemblyName, AssemblyBuilderAccess assemblyBuilderAccess)
{
Expand All @@ -17,5 +16,4 @@ public static Type CreateType(this TypeBuilder typeBuilder)
return typeBuilder.GetTypeInfo().GetType();
}
}
#endif
}
46 changes: 0 additions & 46 deletions Python.Runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -492,60 +492,14 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects)
/// </summary>
internal static unsafe void XIncref(IntPtr op)
{
#if PYTHON_WITH_PYDEBUG || NETSTANDARD
Py_IncRef(op);
return;
#else
var p = (void*)op;
if ((void*)0 != p)
{
if (Is32Bit)
{
(*(int*)p)++;
}
else
{
(*(long*)p)++;
}
}
#endif
}

internal static unsafe void XDecref(IntPtr op)
{
#if PYTHON_WITH_PYDEBUG || NETSTANDARD
Py_DecRef(op);
return;
#else
var p = (void*)op;
if ((void*)0 != p)
{
if (Is32Bit)
{
--(*(int*)p);
}
else
{
--(*(long*)p);
}
if ((*(int*)p) == 0)
{
// PyObject_HEAD: struct _typeobject *ob_type
void* t = Is32Bit
? (void*)(*((uint*)p + 1))
: (void*)(*((ulong*)p + 1));
// PyTypeObject: destructor tp_dealloc
void* f = Is32Bit
? (void*)(*((uint*)t + 6))
: (void*)(*((ulong*)t + 6));
if ((void*)0 == f)
{
return;
}
NativeCall.Impl.Void_Call_1(new IntPtr(f), op);
}
}
#endif
}

internal static unsafe long Refcount(IntPtr op)
Expand Down
2 changes: 1 addition & 1 deletion Python.Test.Embed/TestDomainReload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//
// Unfortunately this means no continuous integration testing for this case.
//
#if !NETSTANDARD && !NETCOREAPP
#if NETFX
namespace Python.EmbeddingTest
{
class TestDomainReload
Expand Down