diff --git a/CHANGELOG.md b/CHANGELOG.md
index 82fccbe35..5bc0c9981 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- Reattach python exception traceback information (#545)
- 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])
- Refactored MethodBinder.Bind in preparation to make it extensible (#829)
+- 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])
- Look for installed Windows 10 sdk's during installation instead of relying on specific versions.
### Fixed
diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj
index a191290ef..9c5f97711 100644
--- a/src/embed_tests/Python.EmbeddingTest.csproj
+++ b/src/embed_tests/Python.EmbeddingTest.csproj
@@ -94,6 +94,7 @@
+
diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs
new file mode 100644
index 000000000..8be207c00
--- /dev/null
+++ b/src/embed_tests/TestInstanceWrapping.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Globalization;
+using NUnit.Framework;
+using Python.Runtime;
+
+namespace Python.EmbeddingTest
+{
+ public class TestInstanceWrapping
+ {
+ [OneTimeSetUp]
+ public void SetUp()
+ {
+ PythonEngine.Initialize();
+ }
+
+ [OneTimeTearDown]
+ public void Dispose()
+ {
+ PythonEngine.Shutdown();
+ }
+
+ // regression test for https://github.com/pythonnet/pythonnet/issues/811
+ [Test]
+ public void OverloadResolution_UnknownToObject()
+ {
+ var overloaded = new Overloaded();
+ using (Py.GIL())
+ {
+ var o = overloaded.ToPython();
+
+ dynamic callWithSelf = PythonEngine.Eval("lambda o: o.ObjOrClass(object())");
+ callWithSelf(o);
+ Assert.AreEqual(Overloaded.Object, overloaded.Value);
+ }
+ }
+
+ class Base {}
+ class Derived: Base { }
+
+ class Overloaded: Derived
+ {
+ public int Value { get; set; }
+ public void IntOrStr(int arg) => this.Value = arg;
+ public void IntOrStr(string arg) =>
+ this.Value = int.Parse(arg, NumberStyles.Integer, CultureInfo.InvariantCulture);
+
+ public const int Object = 1;
+ public const int ConcreteClass = 2;
+ public void ObjOrClass(object _) => this.Value = Object;
+ public void ObjOrClass(Overloaded _) => this.Value = ConcreteClass;
+
+ public const int Base = ConcreteClass + 1;
+ public const int Derived = Base + 1;
+ public void BaseOrDerived(Base _) => this.Value = Base;
+ public void BaseOrDerived(Derived _) => this.Value = Derived;
+ }
+ }
+}
diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs
index 7c53bdcb1..3add8aba0 100644
--- a/src/runtime/converter.cs
+++ b/src/runtime/converter.cs
@@ -398,12 +398,9 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
return ToArray(value, typeof(object[]), out result, setError);
}
- if (setError)
- {
- Exceptions.SetError(Exceptions.TypeError, "value cannot be converted to Object");
- }
-
- return false;
+ Runtime.XIncref(value); // PyObject() assumes ownership
+ result = new PyObject(value);
+ return true;
}
// Conversion to 'Type' is done using the same mappings as above for objects.
diff --git a/src/tests/test_conversion.py b/src/tests/test_conversion.py
index 0ba10a80e..e61eda26c 100644
--- a/src/tests/test_conversion.py
+++ b/src/tests/test_conversion.py
@@ -595,11 +595,10 @@ def test_object_conversion():
# need to test subclass here
- with pytest.raises(TypeError):
- class Foo(object):
- pass
- ob = ConversionTest()
- ob.ObjectField = Foo
+ class Foo(object):
+ pass
+ ob.ObjectField = Foo
+ assert ob.ObjectField == Foo
def test_enum_conversion():
diff --git a/src/tests/test_indexer.py b/src/tests/test_indexer.py
index 6f18550d9..ca4fd3b89 100644
--- a/src/tests/test_indexer.py
+++ b/src/tests/test_indexer.py
@@ -438,13 +438,13 @@ def test_object_indexer():
ob[long(1)] = "long"
assert ob[long(1)] == "long"
- with pytest.raises(TypeError):
- class Eggs(object):
- pass
+ class Eggs(object):
+ pass
- key = Eggs()
- ob = Test.ObjectIndexerTest()
- ob[key] = "wrong"
+ key = Eggs()
+ ob = Test.ObjectIndexerTest()
+ ob[key] = "eggs_key"
+ assert ob[key] == "eggs_key"
def test_interface_indexer():