diff --git a/src/pyinit.jl b/src/pyinit.jl index 7515b12c..13ae1b72 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -27,7 +27,7 @@ const pyxrange = Ref{PyPtr}(0) function pyjlwrap_init() # PyMemberDef stores explicit pointers, hence must be initialized at runtime push!(pyjlwrap_members, PyMemberDef(pyjlwrap_membername, - T_PYSSIZET, sizeof_PyObject_HEAD, READONLY, + T_PYSSIZET, sizeof_pyjlwrap_head, READONLY, pyjlwrap_doc), PyMemberDef(C_NULL,0,0,0,C_NULL)) @@ -57,6 +57,7 @@ function pyjlwrap_init() t.tp_iter = pyjlwrap_getiter_ptr t.tp_hash = sizeof(Py_hash_t) < sizeof(Int) ? pyjlwrap_hash32_ptr : pyjlwrap_hash_ptr + t.tp_weaklistoffset = fieldoffset(Py_jlWrap, 3) end end diff --git a/src/pytype.jl b/src/pytype.jl index 058cc713..387bc56f 100644 --- a/src/pytype.jl +++ b/src/pytype.jl @@ -168,6 +168,7 @@ const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION_ = (0x00000003<<15) # -- most fields can default to 0 except where noted const sizeof_PyObject_HEAD = sizeof(Int) + sizeof(PyPtr) +const sizeof_pyjlwrap_head = sizeof_PyObject_HEAD + sizeof(PyPtr) mutable struct PyTypeObject # PyObject_HEAD (for non-Py_TRACE_REFS build): @@ -325,17 +326,22 @@ struct Py_jlWrap ob_refcnt::Int ob_type::PyPtr + ob_weakrefs::PyPtr jl_value::Any end # destructor for jlwrap instance, assuming it was created with pyjlwrap_new function pyjlwrap_dealloc(o::PyPtr) + p = convert(Ptr{PyPtr}, o) + if unsafe_load(p, 3) != PyPtr_NULL + ccall((@pysym :PyObject_ClearWeakRefs), Cvoid, (PyPtr,), o) + end delete!(pycall_gc, o) return nothing end unsafe_pyjlwrap_to_objref(o::PyPtr) = - unsafe_pointer_to_objref(unsafe_load(convert(Ptr{Ptr{Cvoid}}, o), 3)) + unsafe_pointer_to_objref(unsafe_load(convert(Ptr{Ptr{Cvoid}}, o), 4)) function pyjlwrap_repr(o::PyPtr) try @@ -440,7 +446,8 @@ function pyjlwrap_new(pyT::PyTypeObject, value::Any) pycall_gc[o.o] = value ptr = pointer_from_objref(value) end - unsafe_store!(p, ptr, 3) + unsafe_store!(p, C_NULL, 3) + unsafe_store!(p, ptr, 4) return o end diff --git a/test/runtests.jl b/test/runtests.jl index a1951214..7ca8c8b7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -393,6 +393,15 @@ const PyInt = pyversion < v"3" ? Int : Clonglong @test get(weakdict(Dict(3=>weakdict)),3) == weakdict end + # Weak ref support for pyjlwrap types + let weakref = pyimport("weakref") + bar = TestConstruct(1) + o = PyObject(bar) + @test PyCall.is_pyjlwrap(o) + r = weakref[:ref](o) + @test weakref[:getweakrefcount](o) == 1 + end + # Expose python docs to Julia doc system py""" def foo():