Skip to content

Commit 605c576

Browse files
committed
experiment in DLR-based method binding (project pythonnet#9)
1 parent efe6003 commit 605c576

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/runtime/Python.Runtime.15.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767
</ItemGroup>
6868

6969
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
70+
<PackageReference Include="Microsoft.CSharp">
71+
<Version>4.7.0</Version>
72+
</PackageReference>
7073
<PackageReference Include="System.Security.Permissions" Version="4.4.0" />
7174
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
7275
</ItemGroup>

src/runtime/methodbinder.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
using System.Diagnostics;
66
using System.Linq;
77
using System.Reflection;
8+
using System.Runtime.CompilerServices;
89
using System.Text;
10+
using Microsoft.CSharp.RuntimeBinder;
11+
using CSharpBinder = Microsoft.CSharp.RuntimeBinder.Binder;
912

1013
namespace Python.Runtime
1114
{
@@ -550,6 +553,41 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i
550553

551554
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
552555
{
556+
var method = info ?? methodinfo.First();
557+
int argLen = (int)Runtime.PyTuple_Size(args);
558+
int argCapacity = Math.Max(argLen, method.GetParameters().Length);
559+
var parameters = new List<object>(argCapacity);
560+
var arguments = new List<CSharpArgumentInfo>(argCapacity) {
561+
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
562+
};
563+
for (int argN = 0; argN < argLen; argN++) {
564+
arguments.Add(CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null));
565+
if (!Converter.ToManaged(Runtime.PyTuple_GetItem(args, argN), typeof(object), out var managed, setError: true))
566+
return IntPtr.Zero;
567+
parameters.Add(managed);
568+
}
569+
570+
if (kw != IntPtr.Zero) {
571+
int kwLen = (int)Runtime.PyDict_Size(kw);
572+
var keys = Runtime.PyDict_Keys(kw);
573+
var items = Runtime.PyDict_Values(kw);
574+
for (int kwN = 0; kwN < kwLen; kwN++) {
575+
string argName = Runtime.GetManagedString(Runtime.PyList_GetItem(keys, kwN));
576+
arguments.Add(CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.NamedArgument, argName));
577+
var item = Runtime.PyList_GetItem(items, kwN);
578+
if (!Converter.ToManaged(item.DangerousGetAddress(), typeof(object), out var managed, setError: true))
579+
return IntPtr.Zero;
580+
parameters.Add(managed);
581+
}
582+
}
583+
584+
var dlrBinding = CSharpBinder.InvokeMember(CSharpBinderFlags.ResultDiscarded, method.Name, new Type[0],
585+
method.DeclaringType, arguments);
586+
var callSite = CallSite<Action<CallSite, object, object>>.Create(dlrBinding);
587+
588+
var co = ManagedType.GetManagedObject(inst) as CLRObject;
589+
callSite.Target(callSite, co.inst, parameters[0]);
590+
553591
Binding binding = Bind(inst, args, kw, info, methodinfo);
554592
object result;
555593
IntPtr ts = IntPtr.Zero;

0 commit comments

Comments
 (0)