diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5531bf47..d8683622f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,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 faa55fa27..d351709a4 100644
--- a/src/embed_tests/Python.EmbeddingTest.csproj
+++ b/src/embed_tests/Python.EmbeddingTest.csproj
@@ -89,6 +89,7 @@
+
diff --git a/src/embed_tests/TestInstanceWrapping.cs b/src/embed_tests/TestInstanceWrapping.cs
new file mode 100644
index 000000000..ec275d67a
--- /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(KeyError())");
+ 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 11c67bf82..1883dc32b 100644
--- a/src/runtime/converter.cs
+++ b/src/runtime/converter.cs
@@ -382,12 +382,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.