Skip to content

Commit c355bd6

Browse files
committed
introduced IPyArgumentConverter interface, that controls marshaling of Python objects when calling .NET methods
1 parent 3b938a5 commit c355bd6

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/runtime/methodbinder.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ internal class MethodBinder
1919
public MethodBase[] methods;
2020
public bool init = false;
2121
public bool allow_threads = true;
22+
readonly IPyArgumentConverter pyArgumentConverter = DefaultPyArgumentConverter.Instance;
2223

2324
internal MethodBinder()
2425
{
@@ -326,7 +327,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
326327
continue;
327328
}
328329
var outs = 0;
329-
var margs = TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList,
330+
var margs = this.TryConvertArguments(pi, paramsArray, args, pynargs, kwargDict, defaultArgList,
330331
needsResolution: _methods.Length > 1,
331332
outs: out outs);
332333

@@ -382,7 +383,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
382383
/// <param name="needsResolution"><c>true</c>, if overloading resolution is required</param>
383384
/// <param name="outs">Returns number of output parameters</param>
384385
/// <returns>An array of .NET arguments, that can be passed to a method.</returns>
385-
static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
386+
object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
386387
IntPtr args, int pyArgCount,
387388
Dictionary<string, IntPtr> kwargDict,
388389
ArrayList defaultArgList,
@@ -423,7 +424,9 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
423424
}
424425

425426
bool isOut;
426-
if (!TryConvertArgument(op, parameter.ParameterType, needsResolution, out margs[paramIndex], out isOut))
427+
if (!this.pyArgumentConverter.TryConvertArgument(
428+
op, parameter.ParameterType, needsResolution,
429+
out margs[paramIndex], out isOut))
427430
{
428431
return null;
429432
}
@@ -445,7 +448,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
445448
return margs;
446449
}
447450

448-
static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution,
451+
internal static bool TryConvertArgument(IntPtr op, Type parameterType, bool needsResolution,
449452
out object arg, out bool isOut)
450453
{
451454
arg = null;

src/runtime/pyargconverter.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace Python.Runtime {
2+
using System;
3+
4+
/// <summary>
5+
/// Specifies how to convert Python objects, passed to .NET functions to the expected CLR types.
6+
/// </summary>
7+
public interface IPyArgumentConverter
8+
{
9+
/// <summary>
10+
/// Attempts to convert an argument passed by Python to the specified parameter type.
11+
/// </summary>
12+
/// <param name="pyarg">Unmanaged pointer to the Python argument value</param>
13+
/// <param name="parameterType">The expected type of the parameter</param>
14+
/// <param name="needsResolution"><c>true</c> if the method is overloaded</param>
15+
/// <param name="arg">This parameter will receive the converted value, matching the specified type</param>
16+
/// <param name="isOut">This parameter will be set to <c>true</c>,
17+
/// if the final type needs to be marshaled as an out argument.</param>
18+
/// <returns><c>true</c>, if the object matches requested type,
19+
/// and conversion was successful, otherwise <c>false</c></returns>
20+
bool TryConvertArgument(IntPtr pyarg, Type parameterType,
21+
bool needsResolution, out object arg, out bool isOut);
22+
}
23+
24+
public class DefaultPyArgumentConverter: IPyArgumentConverter {
25+
public static DefaultPyArgumentConverter Instance { get; }= new DefaultPyArgumentConverter();
26+
27+
/// <summary>
28+
/// Attempts to convert an argument passed by Python to the specified parameter type.
29+
/// </summary>
30+
/// <param name="pyarg">Unmanaged pointer to the Python argument value</param>
31+
/// <param name="parameterType">The expected type of the parameter</param>
32+
/// <param name="needsResolution"><c>true</c> if the method is overloaded</param>
33+
/// <param name="arg">This parameter will receive the converted value, matching the specified type</param>
34+
/// <param name="isOut">This parameter will be set to <c>true</c>,
35+
/// if the final type needs to be marshaled as an out argument.</param>
36+
/// <returns><c>true</c>, if the object matches requested type,
37+
/// and conversion was successful, otherwise <c>false</c></returns>
38+
public virtual bool TryConvertArgument(
39+
IntPtr pyarg, Type parameterType, bool needsResolution,
40+
out object arg, out bool isOut)
41+
{
42+
return MethodBinder.TryConvertArgument(
43+
pyarg, parameterType, needsResolution,
44+
out arg, out isOut);
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)