diff --git a/Include/methodobject.h b/Include/methodobject.h index 3cc2ea9308f..0236228617e 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -77,6 +77,7 @@ typedef struct { PyMethodDef *m_ml; /* Description of the C function to call */ PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ PyObject *m_module; /* The __module__ attribute, can be anything */ + PyObject *m_weakreflist; /* List of weak references */ } PyCFunctionObject; #endif diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 854e7865e88..c50b20b9fb3 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -784,7 +784,7 @@ class SizeofTest(unittest.TestCase): # buffer # XXX # builtin_function_or_method - check(len, size('3P')) # XXX check layout + check(len, size('4P')) # XXX check layout # bytearray samples = [b'', b'u'*100000] for sample in samples: diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index adb923f2a38..747627319b1 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -92,6 +92,18 @@ class ReferencesTestCase(TestBase): self.check_basic_callback(create_function) self.check_basic_callback(create_bound_method) + @support.cpython_only + def test_cfunction(self): + import _testcapi + create_cfunction = _testcapi.create_cfunction + f = create_cfunction() + wr = weakref.ref(f) + self.assertIs(wr(), f) + del f + self.assertIsNone(wr()) + self.check_basic_ref(create_cfunction) + self.check_basic_callback(create_cfunction) + def test_multiple_callbacks(self): o = C() ref1 = weakref.ref(o, self.callback) diff --git a/Misc/ACKS b/Misc/ACKS index 09b68d181a3..60d6f7fd5f9 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1484,6 +1484,7 @@ Gordon Worley Darren Worrall Thomas Wouters Daniel Wozniak +Wei Wu Heiko Wundram Doug Wyatt Robert Xiao diff --git a/Misc/NEWS b/Misc/NEWS index 877384f1797..4a3ebd56e5b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: TBA Core and Builtins ----------------- +- Issue #22116: C functions and methods (of the 'builtin_function_or_method' + type) can now be weakref'ed. Patch by Wei Wu. + - Issue #22077: Improve index error messages for bytearrays, bytes, lists, and tuples by adding 'or slices'. Added ', not m_weakreflist = NULL; op->m_ml = ml; Py_XINCREF(self); op->m_self = self; @@ -147,6 +148,9 @@ static void meth_dealloc(PyCFunctionObject *m) { _PyObject_GC_UNTRACK(m); + if (m->m_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject*) m); + } Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); if (numfree < PyCFunction_MAXFREELIST) { @@ -352,7 +356,7 @@ PyTypeObject PyCFunction_Type = { (traverseproc)meth_traverse, /* tp_traverse */ 0, /* tp_clear */ meth_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ meth_methods, /* tp_methods */