diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index ef3aa3e18..1170efe7a 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -126,6 +126,12 @@ internal static IntPtr ToPython(T value) internal static IntPtr ToPython(Object value, Type type) { + if(value is PyObject) + { + IntPtr handle = ((PyObject)value).Handle; + Runtime.XIncref(handle); + return handle; + } IntPtr result = IntPtr.Zero; // Null always converts to None in Python. @@ -265,6 +271,13 @@ internal static bool ToManaged(IntPtr value, Type type, internal static bool ToManagedValue(IntPtr value, Type obType, out Object result, bool setError) { + if (obType == typeof(PyObject)) + { + Runtime.XIncref(value); // PyObject() assumes ownership + result = new PyObject(value); + return true; + } + // Common case: if the Python value is a wrapped managed object // instance, just return the wrapped object. ManagedType mt = ManagedType.GetManagedObject(value); diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 323d50da7..ba44c0c21 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -127,6 +127,16 @@ protected virtual void Dispose(bool disposing) } } + public long RefCount + { + get + { + if(!disposed) + return Runtime.Refcount(obj); + return -1; + } + } + public void Dispose() { Dispose(true); diff --git a/src/testing/callbacktest.cs b/src/testing/callbacktest.cs index 81389289d..70c7bbc9e 100644 --- a/src/testing/callbacktest.cs +++ b/src/testing/callbacktest.cs @@ -28,4 +28,18 @@ public string Call_simpleDefaultArg_WithEmptyArgs(string moduleName) } } } + + //========================================================================== + // Tests calling from Python into C# and back into Python using a PyObject. + // SelfCallbackTest should be inherited by a Python class. + // Used in test_class.py / testCallback + //========================================================================== + public class SelfCallbackTest + { + public void Callback(Runtime.PyObject self) + { + using (Runtime.Py.GIL()) + ((dynamic)self).PyCallback(self); + } + } } diff --git a/src/tests/test_class.py b/src/tests/test_class.py index afb631622..9e2af14da 100644 --- a/src/tests/test_class.py +++ b/src/tests/test_class.py @@ -250,6 +250,21 @@ def testComparisons(self): c2 = ClassTest() self.assertRaises(TypeError, lambda: c1 < c2) + def testSelfCallback(self): + """ Test calling back and forth between this and a c# baseclass.""" + class CallbackUser(Test.SelfCallbackTest): + def DoCallback(self): + self.PyCallbackWasCalled = False + self.SameReference = False + return self.Callback(self) + def PyCallback(self, self2): + self.PyCallbackWasCalled = True + self.SameReference = self == self2 + + testobj = CallbackUser() + testobj.DoCallback() + self.assertTrue(testobj.PyCallbackWasCalled) + self.assertTrue(testobj.SameReference) class ClassicClass: def kind(self):