Issue #22116: C functions and methods (of the 'builtin_function_or_method' type) can now be weakref'ed. Patch by Wei Wu.

This commit is contained in:
Antoine Pitrou 2014-08-06 19:31:40 -04:00
parent f3440c6881
commit b349e4c929
7 changed files with 39 additions and 2 deletions

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -1484,6 +1484,7 @@ Gordon Worley
Darren Worrall
Thomas Wouters
Daniel Wozniak
Wei Wu
Heiko Wundram
Doug Wyatt
Robert Xiao

View File

@ -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 <typename' for bytearrays.
Original patch by Claudiu Popa.

View File

@ -2653,6 +2653,21 @@ with_tp_del(PyObject *self, PyObject *args)
return obj;
}
static PyMethodDef ml;
static PyObject *
create_cfunction(PyObject *self, PyObject *args)
{
return PyCFunction_NewEx(&ml, self, NULL);
}
static PyMethodDef ml = {
"create_cfunction",
create_cfunction,
METH_NOARGS,
NULL
};
static PyObject *
_test_incref(PyObject *ob)
{
@ -3186,6 +3201,7 @@ static PyMethodDef TestMethods[] = {
{"pytime_object_to_timeval", test_pytime_object_to_timeval, METH_VARARGS},
{"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
{"with_tp_del", with_tp_del, METH_VARARGS},
{"create_cfunction", create_cfunction, METH_NOARGS},
{"test_pymem_alloc0",
(PyCFunction)test_pymem_alloc0, METH_NOARGS},
{"test_pymem_setrawallocators",

View File

@ -37,6 +37,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
if (op == NULL)
return NULL;
}
op->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 */