-
Notifications
You must be signed in to change notification settings - Fork 752
Weakref support #1267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Weakref support #1267
Changes from all commits
d6c9716
5d57e5a
f08813c
b014ce1
e7f97a9
b68f0a4
b4b1cff
ff35e6d
ea3d47a
958a8eb
53ad8d9
647bc8a
f474039
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
using NUnit.Framework; | ||
|
||
using Python.Runtime; | ||
|
||
using PyRuntime = Python.Runtime.Runtime; | ||
|
||
namespace Python.EmbeddingTest | ||
{ | ||
public class TestClass | ||
{ | ||
public class MyClass | ||
{ | ||
} | ||
|
||
[OneTimeSetUp] | ||
public void SetUp() | ||
{ | ||
PythonEngine.Initialize(); | ||
} | ||
|
||
[OneTimeTearDown] | ||
public void Dispose() | ||
{ | ||
PythonEngine.Shutdown(); | ||
} | ||
|
||
[Test] | ||
public void WeakRefForClrObject() | ||
{ | ||
var obj = new MyClass(); | ||
using var scope = Py.CreateScope(); | ||
scope.Set("clr_obj", obj); | ||
scope.Exec(@" 10000 span> | ||
import weakref | ||
ref = weakref.ref(clr_obj) | ||
"); | ||
using PyObject pyobj = scope.Get("clr_obj"); | ||
ValidateAttachedGCHandle(obj, pyobj.Handle); | ||
} | ||
|
||
[Test] | ||
public void WeakRefForSubClass() | ||
{ | ||
using (var scope = Py.CreateScope()) | ||
{ | ||
scope.Exec(@" | ||
from Python.EmbeddingTest import TestClass | ||
import weakref | ||
|
||
class Sub(TestClass.MyClass): | ||
pass | ||
|
||
obj = Sub() | ||
ref = weakref.ref(obj) | ||
"); | ||
using (PyObject pyobj = scope.Get("obj")) | ||
{ | ||
IntPtr op = pyobj.Handle; | ||
IntPtr type = PyRuntime.PyObject_TYPE(op); | ||
IntPtr clrHandle = Marshal.ReadIntPtr(op, ObjectOffset.magic(type)); | ||
var clobj = (CLRObject)GCHandle.FromIntPtr(clrHandle).Target; | ||
Assert.IsTrue(clobj.inst is MyClass); | ||
} | ||
} | ||
} | ||
|
||
private static void ValidateAttachedGCHandle(object obj, IntPtr op) | ||
{ | ||
IntPtr type = PyRuntime.PyObject_TYPE(op); | ||
IntPtr clrHandle = Marshal.ReadIntPtr(op, ObjectOffset.magic(type)); | ||
var clobj = (CLRObject)GCHandle.FromIntPtr(clrHandle).Target; | ||
Assert.True(ReferenceEquals(clobj.inst, obj)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,13 @@ internal static Exception ToException(IntPtr ob) | |
} | ||
return Runtime.PyUnicode_FromString(message); | ||
} | ||
|
||
public static int tp_init(IntPtr ob, IntPtr args, IntPtr kwds) | ||
{ | ||
Exceptions.SetArgsAndCause(ob); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, move the original comment here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: You seem to have moved this from
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment on |
||
return 0; | ||
} | ||
|
||
} | ||
|
||
/// <summary> | ||
|
@@ -180,16 +187,23 @@ internal static void SetArgsAndCause(IntPtr ob) | |
args = Runtime.PyTuple_New(0); | ||
} | ||
|
||
Marshal.WriteIntPtr(ob, ExceptionOffset.args, args); | ||
|
||
int baseOffset = OriginalObjectOffsets.Size; | ||
Runtime.Py_SETREF(ob, baseOffset + ExceptionOffset.args, args); | ||
|
||
if (e.InnerException != null) | ||
{ | ||
// Note: For an AggregateException, InnerException is only the first of the InnerExceptions. | ||
IntPtr cause = CLRObject.GetInstHandle(e.InnerException); | ||
Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause); | ||
IntPtr cause = GetExceptHandle(e.InnerException); | ||
Runtime.Py_SETREF(ob, baseOffset + ExceptionOffset.cause, cause); | ||
} | ||
} | ||
|
||
internal static IntPtr GetExceptHandle(Exception e) | ||
{ | ||
IntPtr op = CLRObject.GetInstHandle(e); | ||
SetArgsAndCause(op); | ||
return op; | ||
} | ||
|
||
/// <summary> | ||
/// Shortcut for (pointer == NULL) -> throw PythonException | ||
/// </summary> | ||
|
@@ -289,7 +303,7 @@ public static void SetError(Exception e) | |
return; | ||
} | ||
|
||
IntPtr op = CLRObject.GetInstHandle(e); | ||
IntPtr op = GetExceptHandle(e); | ||
IntPtr etype = Runtime.PyObject_GetAttr(op, PyIdentifier.__class__); | ||
Runtime.PyErr_SetObject(new BorrowedReference(etype), new BorrowedReference(op)); | ||
Runtime.XDecref(etype); | ||
|
Uh oh!
There was an error while loading. Please reload this page.