Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 43c972d

Browse files
lostmsufilmor
authored andcommitted
Enable C# parameters of type object accept any argument, passed from Python (#853)
* added a regression test for #881 #811 * when converting to object, wrap values of unknown type into PyObject instead of failing This enables overload resolution with object parameters to behave the same way PyObject parameters behave - e.g. allow any Python object to be passed as PyObject as fallback. Resolves #811
1 parent 0d6194d commit 43c972d

File tree

4 files changed

+63
-6
lines changed

4 files changed

+63
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
4141
- Reattach python exception traceback information (#545)
4242
- PythonEngine.Intialize will now call `Py_InitializeEx` with a default value of 0, so signals will not be configured by default on embedding. This is different from the previous behaviour, where `Py_Initialize` was called instead, which sets initSigs to 1. ([#449][i449])
4343
- Refactored MethodBinder.Bind in preparation to make it extensible (#829)
44+
- When calling C# from Python, enable passing argument of any type to a parameter of C# type `object` by wrapping it into `PyObject` instance. ([#881][i881])
4445
- Look for installed Windows 10 sdk's during installation instead of relying on specific versions.
4546

4647
### Fixed

src/embed_tests/Python.EmbeddingTest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<Compile Include="TestDomainReload.cs" />
9090
<Compile Include="TestExample.cs" />
9191
<Compile Include="TestFinalizer.cs" />
92+
<Compile Include="TestInstanceWrapping.cs" />
9293
<Compile Include="TestPyAnsiString.cs" />
9394
<Compile Include="TestPyFloat.cs" />
9495
<Compile Include="TestPyInt.cs" />
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Globalization;
3+
using NUnit.Framework;
4+
using Python.Runtime;
5+
6+
namespace Python.EmbeddingTest
7+
{
8+
public class TestInstanceWrapping
9+
{
10+
[OneTimeSetUp]
11+
public void SetUp()
12+
{
13+
PythonEngine.Initialize();
14+
}
15+
16+
[OneTimeTearDown]
17+
public void Dispose()
18+
{
19+
PythonEngine.Shutdown();
20+
}
21+
22+
// regression test for https://github.com/pythonnet/pythonnet/issues/811
23+
[Test]
24+
public void OverloadResolution_UnknownToObject()
25+
{
26+
var overloaded = new Overloaded();
27+
using (Py.GIL())
28+
{
29+
var o = overloaded.ToPython();
30+
31+
dynamic callWithSelf = PythonEngine.Eval("lambda o: o.ObjOrClass(KeyError())");
32+
callWithSelf(o);
33+
Assert.AreEqual(Overloaded.Object, overloaded.Value);
34+
}
35+
}
36+
37+
class Base {}
38+
class Derived: Base { }
39+
40+
class Overloaded: Derived
41+
{
42+
public int Value { get; set; }
43+
public void IntOrStr(int arg) => this.Value = arg;
44+
public void IntOrStr(string arg) =>
45+
this.Value = int.Parse(arg, NumberStyles.Integer, CultureInfo.InvariantCulture);
46+
47+
public const int Object = 1;
48+
public const int ConcreteClass = 2;
49+
public void ObjOrClass(object _) => this.Value = Object;
50+
public void ObjOrClass(Overloaded _) => this.Value = ConcreteClass;
51+
52+
public const int Base = ConcreteClass + 1;
53+
public const int Derived = Base + 1;
54+
public void BaseOrDerived(Base _) => this.Value = Base;
55+
public void BaseOrDerived(Derived _) => this.Value = Derived;
56+
}
57+
}
58+
}

src/runtime/converter.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,9 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
382382
return ToArray(value, typeof(object[]), out result, setError);
383383
}
384384

385-
if (setError)
386-
{
387-
Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object");
388-
}
389-
390-
return false;
385+
Runtime.XIncref(value); // PyObject() assumes ownership
386+
result = new PyObject(value);
387+
return true;
391388
}
392389

393390
// Conversion to 'Type' is done using the same mappings as above for objects.

0 commit comments

Comments
 (0)