Skip to content

Commit e6dd71d

Browse files
authored
gh-123961: Clean up curses C API/capsule (#124907)
1 parent 9eeb21b commit e6dd71d

File tree

1 file changed

+77
-50
lines changed

1 file changed

+77
-50
lines changed

Modules/_cursesmodule.c

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -626,24 +626,6 @@ class component_converter(CConverter):
626626
[python start generated code]*/
627627
/*[python end generated code: output=da39a3ee5e6b4b0d input=38e9be01d33927fb]*/
628628

629-
/* Function versions of the 3 functions for testing whether curses has been
630-
initialised or not. */
631-
632-
static int func_PyCursesSetupTermCalled(void)
633-
{
634-
return _PyCursesCheckFunction(curses_setupterm_called, "setupterm");
635-
}
636-
637-
static int func_PyCursesInitialised(void)
638-
{
639-
return _PyCursesCheckFunction(curses_initscr_called, "initscr");
640-
}
641-
642-
static int func_PyCursesInitialisedColor(void)
643-
{
644-
return _PyCursesCheckFunction(curses_start_color_called, "start_color");
645-
}
646-
647629
/*****************************************************************************
648630
The Window Object
649631
******************************************************************************/
@@ -4853,29 +4835,73 @@ static PyMethodDef PyCurses_methods[] = {
48534835
{NULL, NULL} /* sentinel */
48544836
};
48554837

4856-
/* Initialization function for the module */
4838+
/* Module C API */
48574839

4840+
/* Function versions of the 3 functions for testing whether curses has been
4841+
initialised or not. */
48584842

4859-
static struct PyModuleDef _cursesmodule = {
4860-
PyModuleDef_HEAD_INIT,
4861-
"_curses",
4862-
NULL,
4863-
-1,
4864-
PyCurses_methods,
4865-
NULL,
4866-
NULL,
4867-
NULL,
4868-
NULL
4869-
};
4843+
static inline int
4844+
curses_capi_setupterm_called(void)
4845+
{
4846+
return _PyCursesCheckFunction(curses_setupterm_called, "setupterm");
4847+
}
4848+
4849+
static inline int
4850+
curses_capi_initscr_called(void)
4851+
{
4852+
return _PyCursesCheckFunction(curses_initscr_called, "initscr");
4853+
}
4854+
4855+
static inline int
4856+
curses_capi_start_color_called(void)
4857+
{
4858+
return _PyCursesCheckFunction(curses_start_color_called, "start_color");
4859+
}
4860+
4861+
static void *
4862+
curses_capi_new(_cursesmodule_state *state)
4863+
{
4864+
assert(state->window_type != NULL);
4865+
void **capi = (void **)PyMem_Calloc(PyCurses_API_pointers, sizeof(void *));
4866+
if (capi == NULL) {
4867+
PyErr_NoMemory();
4868+
return NULL;
4869+
}
4870+
capi[0] = (void *)Py_NewRef(state->window_type);
4871+
capi[1] = curses_capi_setupterm_called;
4872+
capi[2] = curses_capi_initscr_called;
4873+
capi[3] = curses_capi_start_color_called;
4874+
return (void *)capi;
4875+
}
48704876

48714877
static void
4872-
curses_destructor(PyObject *op)
4878+
curses_capi_free(void *capi)
48734879
{
4874-
void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
4875-
Py_DECREF(*(void **)ptr);
4876-
PyMem_Free(ptr);
4880+
assert(capi != NULL);
4881+
void **capi_ptr = (void **)capi;
4882+
assert(capi_ptr[0] != NULL);
4883+
Py_DECREF(capi_ptr[0]); // decref curses window type
4884+
PyMem_Free(capi_ptr);
48774885
}
48784886

4887+
/* Module C API Capsule */
4888+
4889+
static void
4890+
curses_capi_capsule_destructor(PyObject *op)
4891+
{
4892+
void *capi = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
4893+
curses_capi_free(capi);
4894+
}
4895+
4896+
static PyObject *
4897+
curses_capi_capsule_new(void *capi)
4898+
{
4899+
return PyCapsule_New(capi, PyCurses_CAPSULE_NAME,
4900+
curses_capi_capsule_destructor);
4901+
}
4902+
4903+
/* Module initialization */
4904+
48794905
static int
48804906
cursesmodule_exec(PyObject *module)
48814907
{
@@ -4895,27 +4921,19 @@ cursesmodule_exec(PyObject *module)
48954921
return -1;
48964922
}
48974923

4898-
void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *));
4899-
if (PyCurses_API == NULL) {
4900-
PyErr_NoMemory();
4924+
/* Create the C API object */
4925+
void *capi = curses_capi_new(state);
4926+
if (capi == NULL) {
49014927
return -1;
49024928
}
4903-
/* Initialize the C API pointer array */
4904-
PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type);
4905-
PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled;
4906-
PyCurses_API[2] = (void *)func_PyCursesInitialised;
4907-
PyCurses_API[3] = (void *)func_PyCursesInitialisedColor;
4908-
49094929
/* Add a capsule for the C API */
4910-
PyObject *c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME,
4911-
curses_destructor);
4912-
if (c_api_object == NULL) {
4913-
Py_DECREF(PyCurses_API[0]);
4914-
PyMem_Free(PyCurses_API);
4930+
PyObject *capi_capsule = curses_capi_capsule_new(capi);
4931+
if (capi_capsule == NULL) {
4932+
curses_capi_free(capi);
49154933
return -1;
49164934
}
4917-
int rc = PyDict_SetItemString(module_dict, "_C_API", c_api_object);
4918-
Py_DECREF(c_api_object);
4935+
int rc = PyDict_SetItemString(module_dict, "_C_API", capi_capsule);
4936+
Py_DECREF(capi_capsule);
49194937
if (rc < 0) {
49204938
return -1;
49214939
}
@@ -5118,6 +5136,15 @@ cursesmodule_exec(PyObject *module)
51185136
return 0;
51195137
}
51205138

5139+
/* Initialization function for the module */
5140+
5141+
static struct PyModuleDef _cursesmodule = {
5142+
PyModuleDef_HEAD_INIT,
5143+
.m_name = "_curses",
5144+
.m_size = -1,
5145+
.m_methods = PyCurses_methods,
5146+
};
5147+
51215148
PyMODINIT_FUNC
51225149
PyInit__curses(void)
51235150
{

0 commit comments

Comments
 (0)