/ext/pycall/gc.c

https://github.com/mrkn/pycall.rb · C · 74 lines · 59 code · 15 blank · 0 comment · 2 complexity · 286e5f503625c9b48720799cddd57193 MD5 · raw file

  1. #include "pycall_internal.h"
  2. static ID id_gcguard_table;
  3. static PyObject *weakref_callback_pyobj;
  4. static PyObject *gcguard_weakref_destroyed(PyObject *self, PyObject *weakref);
  5. PyMethodDef gcguard_weakref_callback_def = {
  6. "_gcguard_weakref_destroyed", (PyCFunction) gcguard_weakref_destroyed, Py_METH_O
  7. };
  8. static PyObject *
  9. gcguard_weakref_destroyed(PyObject *self, PyObject *weakref)
  10. {
  11. pycall_gcguard_delete(weakref);
  12. Py_API(Py_DecRef)(weakref);
  13. Py_API(Py_IncRef)(Py_API(_Py_NoneStruct));
  14. return Py_API(_Py_NoneStruct);
  15. }
  16. void
  17. pycall_gcguard_aset(PyObject *pyobj, VALUE rbobj)
  18. {
  19. VALUE table = rb_ivar_get(mPyCall, id_gcguard_table);
  20. rb_hash_aset(table, PTR2NUM(pyobj), rbobj);
  21. }
  22. void
  23. pycall_gcguard_delete(PyObject *pyobj)
  24. {
  25. VALUE table = rb_ivar_get(mPyCall, id_gcguard_table);
  26. rb_hash_delete(table, PTR2NUM(pyobj));
  27. }
  28. void
  29. pycall_gcguard_register_pyrubyobj(PyObject *pyobj)
  30. {
  31. VALUE rbobj;
  32. if (!PyRuby_Check(pyobj)) {
  33. rb_raise(rb_eTypeError, "wrong type of python object %s (expect PyCall.ruby_object)", Py_TYPE(pyobj)->tp_name);
  34. }
  35. rbobj = PyRuby_get_ruby_object(pyobj);
  36. pycall_gcguard_aset(pyobj, rbobj);
  37. }
  38. void
  39. pycall_gcguard_unregister_pyrubyobj(PyObject *pyobj)
  40. {
  41. if (!PyRuby_Check(pyobj)) {
  42. rb_raise(rb_eTypeError, "wrong type of python object %s (expect PyCall.ruby_object)", Py_TYPE(pyobj)->tp_name);
  43. }
  44. pycall_gcguard_delete(pyobj);
  45. }
  46. void
  47. pycall_gcguard_register(PyObject *pyobj, VALUE obj)
  48. {
  49. PyObject *wref;
  50. wref = Py_API(PyWeakref_NewRef)(pyobj, weakref_callback_pyobj);
  51. pycall_gcguard_aset(wref, obj);
  52. }
  53. void
  54. pycall_init_gcguard(void)
  55. {
  56. id_gcguard_table = rb_intern("gcguard_table");
  57. rb_ivar_set(mPyCall, id_gcguard_table, rb_hash_new());
  58. weakref_callback_pyobj = Py_API(PyCFunction_NewEx)(&gcguard_weakref_callback_def, NULL, NULL);
  59. }