module PyCall::GCGuard

Public Class Methods

embed(pyobj, obj) click to toggle source
# File lib/pycall/gc_guard.rb, line 57
def self.embed(pyobj, obj)
  pyptr = pyobj.respond_to?(:__pyobj__) ? pyobj.__pyobj__ : pyobj
  raise TypeError, "The argument must be a Python object" unless pyptr.kind_of? LibPython::PyObjectStruct
  wo = LibPython.PyWeakref_NewRef(pyptr, weakref_callback)
  register(wo, obj)
  pyobj
end
guarded_object_count() click to toggle source
# File lib/pycall/gc_guard.rb, line 53
def self.guarded_object_count
  @gc_guard.length
end
register(pyobj, obj) click to toggle source
# File lib/pycall/gc_guard.rb, line 42
def self.register(pyobj, obj)
  key = Key.new(pyobj)
  @gc_guard[key] ||= []
  @gc_guard[key] << obj
end
unregister(pyobj) click to toggle source
# File lib/pycall/gc_guard.rb, line 48
def self.unregister(pyobj)
  key = Key.new(pyobj)
  @gc_guard.delete(key).tap { key.release }
end

Private Class Methods

weakref_callback() click to toggle source
# File lib/pycall/gc_guard.rb, line 65
                     def self.weakref_callback
  unless @weakref_callback
    @weakref_callback_func = FFI::Function.new(
      LibPython::PyObjectStruct.ptr,
      [LibPython::PyObjectStruct.ptr, LibPython::PyObjectStruct.ptr]
    ) do |callback, pyptr|
      GCGuard.unregister(pyptr)
      # LibPython.Py_DecRef(pyptr)
      # LibPython.Py_IncRef(PyCall.None)
      next PyCall.None
    end
    method_def = LibPython::PyMethodDef.new("weakref_callback", @weakref_callback_func, LibPython::METH_O, nil)
    @weakref_callback = LibPython.PyCFunction_NewEx(method_def, nil, nil).tap {|po| LibPython.Py_IncRef(po) }
  end
  @weakref_callback
end