Skip to content

Commit

Permalink
gh-117142: ctypes: Unify meta tp slot functions (GH-117143)
Browse files Browse the repository at this point in the history
Integrates the following ctypes meta tp slot functions:
* `CDataType_traverse()` into `CType_Type_traverse()`.
* `CDataType_clear()` into `CType_Type_clear()`.
* `CDataType_dealloc()` into `CType_Type_dealloc()`.
* `CDataType_repeat()` into `CType_Type_repeat()`.
  • Loading branch information
neonene authored Apr 1, 2024
1 parent 3de09ca commit dd44ab9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 73 deletions.
109 changes: 36 additions & 73 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,19 +441,35 @@ static PyType_Spec structparam_spec = {
static int
CType_Type_traverse(PyObject *self, visitproc visit, void *arg)
{
ctypes_state *st = GLOBAL_STATE();
if (st && st->PyCType_Type) {
StgInfo *info;
if (PyStgInfo_FromType(st, self, &info) < 0) {
PyErr_WriteUnraisable(self);
}
if (info) {
Py_VISIT(info->proto);
Py_VISIT(info->argtypes);
Py_VISIT(info->converters);
Py_VISIT(info->restype);
Py_VISIT(info->checker);
Py_VISIT(info->module);
}
}
Py_VISIT(Py_TYPE(self));
return 0;
return PyType_Type.tp_traverse(self, visit, arg);
}

static void
_ctype_clear_stginfo(StgInfo *info)
void
ctype_clear_stginfo(StgInfo *info)
{
assert(info);
Py_CLEAR(info->proto);
Py_CLEAR(info->argtypes);
Py_CLEAR(info->converters);
Py_CLEAR(info->restype);
Py_CLEAR(info->checker);
Py_CLEAR(info->module);
}

static int
Expand All @@ -463,13 +479,13 @@ CType_Type_clear(PyObject *self)
if (st && st->PyCType_Type) {
StgInfo *info;
if (PyStgInfo_FromType(st, self, &info) < 0) {
return -1;
PyErr_WriteUnraisable(self);
}
if (info) {
_ctype_clear_stginfo(info);
ctype_clear_stginfo(info);
}
}
return 0;
return PyType_Type.tp_clear(self);
}

static void
Expand All @@ -489,7 +505,7 @@ CType_Type_dealloc(PyObject *self)
info->format = NULL;
PyMem_Free(info->shape);
info->shape = NULL;
_ctype_clear_stginfo(info);
ctype_clear_stginfo(info);
}
}

Expand Down Expand Up @@ -522,6 +538,10 @@ CType_Type_sizeof(PyObject *self)
return PyLong_FromSsize_t(size);
}

static PyObject *
CType_Type_repeat(PyObject *self, Py_ssize_t length);


static PyMethodDef ctype_methods[] = {
{"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof),
METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")},
Expand All @@ -533,6 +553,8 @@ static PyType_Slot ctype_type_slots[] = {
{Py_tp_clear, CType_Type_clear},
{Py_tp_dealloc, CType_Type_dealloc},
{Py_tp_methods, ctype_methods},
// Sequence protocol.
{Py_sq_repeat, CType_Type_repeat},
{0, NULL},
};

Expand Down Expand Up @@ -978,7 +1000,7 @@ static PyMethodDef CDataType_methods[] = {
};

static PyObject *
CDataType_repeat(PyObject *self, Py_ssize_t length)
CType_Type_repeat(PyObject *self, Py_ssize_t length)
{
if (length < 0)
return PyErr_Format(PyExc_ValueError,
Expand All @@ -988,35 +1010,6 @@ CDataType_repeat(PyObject *self, Py_ssize_t length)
return PyCArrayType_from_ctype(st, self, length);
}

static int
CDataType_clear(PyTypeObject *self)
{
ctypes_state *st = GLOBAL_STATE();
StgInfo *info;
if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) {
return -1;
}
if (info) {
Py_CLEAR(info->proto);
}
return PyType_Type.tp_clear((PyObject *)self);
}

static int
CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg)
{
ctypes_state *st = GLOBAL_STATE();
StgInfo *info;
if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) {
return -1;
}
if (info) {
Py_VISIT(info->proto);
}
Py_VISIT(Py_TYPE(self));
return PyType_Type.tp_traverse((PyObject *)self, visit, arg);
}

static int
PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value)
{
Expand Down Expand Up @@ -1047,39 +1040,29 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value)
static PyType_Slot pycstruct_type_slots[] = {
{Py_tp_setattro, PyCStructType_setattro},
{Py_tp_doc, PyDoc_STR("metatype for the CData Objects")},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_clear, CDataType_clear},
{Py_tp_methods, CDataType_methods},
{Py_tp_init, PyCStructType_init},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec pycstruct_type_spec = {
.name = "_ctypes.PyCStructType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = pycstruct_type_slots,
};

static PyType_Slot union_type_slots[] = {
{Py_tp_setattro, UnionType_setattro},
{Py_tp_doc, PyDoc_STR("metatype for the Union Objects")},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_clear, CDataType_clear},
{Py_tp_methods, CDataType_methods},
{Py_tp_init, UnionType_init},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec union_type_spec = {
.name = "_ctypes.UnionType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = union_type_slots,
};
Expand Down Expand Up @@ -1305,19 +1288,14 @@ static PyMethodDef PyCPointerType_methods[] = {

static PyType_Slot pycpointer_type_slots[] = {
{Py_tp_doc, PyDoc_STR("metatype for the Pointer Objects")},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_clear, CDataType_clear},
{Py_tp_methods, PyCPointerType_methods},
{Py_tp_init, PyCPointerType_init},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec pycpointer_type_spec = {
.name = "_ctypes.PyCPointerType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = pycpointer_type_slots,
};
Expand Down Expand Up @@ -1640,19 +1618,14 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds)

static PyType_Slot pycarray_type_slots[] = {
{Py_tp_doc, PyDoc_STR("metatype for the Array Objects")},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_methods, CDataType_methods},
{Py_tp_init, PyCArrayType_init},
{Py_tp_clear, CDataType_clear},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec pycarray_type_spec = {
.name = "_ctypes.PyCArrayType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = pycarray_type_slots,
};
Expand Down Expand Up @@ -2315,17 +2288,12 @@ static PyType_Slot pycsimple_type_slots[] = {
{Py_tp_doc, PyDoc_STR("metatype for the PyCSimpleType Objects")},
{Py_tp_methods, PyCSimpleType_methods},
{Py_tp_init, PyCSimpleType_init},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_clear, CDataType_clear},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec pycsimple_type_spec = {
.name = "_ctypes.PyCSimpleType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = pycsimple_type_slots,
};
Expand Down Expand Up @@ -2570,19 +2538,14 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds)

static PyType_Slot pycfuncptr_type_slots[] = {
{Py_tp_doc, PyDoc_STR("metatype for C function pointers")},
{Py_tp_traverse, CDataType_traverse},
{Py_tp_clear, CDataType_clear},
{Py_tp_methods, CDataType_methods},
{Py_tp_init, PyCFuncPtrType_init},

// Sequence protocol.
{Py_sq_repeat, CDataType_repeat},
{0, NULL},
};

static PyType_Spec pycfuncptr_type_spec = {
.name = "_ctypes.PyCFuncPtrType",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = pycfuncptr_type_slots,
};
Expand Down
8 changes: 8 additions & 0 deletions Modules/_ctypes/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ typedef struct {
PyObject *converters; /* tuple([t.from_param for t in argtypes]) */
PyObject *restype; /* CDataObject or NULL */
PyObject *checker;
PyObject *module;
int flags; /* calling convention and such */

/* pep3118 fields, pointers need PyMem_Free */
Expand All @@ -313,6 +314,7 @@ typedef struct {
} StgInfo;

extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info);
extern void ctype_clear_stginfo(StgInfo *info);

typedef int(* PPROC)(void);

Expand Down Expand Up @@ -481,6 +483,12 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type)
type->tp_name);
return NULL;
}
PyObject *module = PyType_GetModule(state->PyCType_Type);
if (!module) {
return NULL;
}
info->module = Py_NewRef(module);

info->initialized = 1;
return info;
}
2 changes: 2 additions & 0 deletions Modules/_ctypes/stgdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info)
{
Py_ssize_t size;

ctype_clear_stginfo(dst_info);
PyMem_Free(dst_info->ffi_type_pointer.elements);
PyMem_Free(dst_info->format);
dst_info->format = NULL;
Expand All @@ -39,6 +40,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info)
Py_XINCREF(dst_info->converters);
Py_XINCREF(dst_info->restype);
Py_XINCREF(dst_info->checker);
Py_XINCREF(dst_info->module);

if (src_info->format) {
dst_info->format = PyMem_Malloc(strlen(src_info->format) + 1);
Expand Down

0 comments on commit dd44ab9

Please sign in to comment.