8000 bpo-41798: Allocate the _datetime.datetime_CAPI on the heap memory (G… · python/cpython@1ab0459 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1ab0459

Browse files
authored
bpo-41798: Allocate the _datetime.datetime_CAPI on the heap memory (GH-24096)
1 parent f22b7ca commit 1ab0459

File tree

1 file changed

+43
-21
lines changed

1 file changed

+43
-21
lines changed

Modules/_datetimemodule.c

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6473,26 +6473,44 @@ static PyMethodDef module_methods[] = {
64736473
{NULL, NULL}
64746474
};
64756475

6476-
/* C API. Clients get at this via PyDateTime_IMPORT, defined in
6477-
* datetime.h.
6476+
/* Get a new C API by calling this function.
6477+
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
64786478
*/
6479-
static PyDateTime_CAPI CAPI = {
6480-
&PyDateTime_DateType,
6481-
&PyDateTime_DateTimeType,
6482-
&PyDateTime_TimeType,
6483-
&PyDateTime_DeltaType,
6484-
&PyDateTime_TZInfoType,
6485-
NULL, // PyDatetime_TimeZone_UTC not initialized yet
6486-
new_date_ex,
6487-
new_datetime_ex,
6488-
new_time_ex,
6489-
new_delta_ex,
6490-
new_timezone,
6491-
datetime_fromtimestamp,
6492-
datetime_date_fromtimestamp_capi,
6493-
new_datetime_ex2,
6494-
new_time_ex2
6495-
};
6479+
static inline PyDateTime_CAPI *
6480+
get_datetime_capi(void)
6481+
{
6482+
PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI));
6483+
if (capi == NULL) {
6484+
PyErr_NoMemory();
6485+
return NULL;
6486+
}
6487+
capi->DateType = &PyDateTime_DateType;
6488+
capi->DateTimeType = &PyDateTime_DateTimeType;
6489+
capi->TimeType = &PyDateTime_TimeType;
6490+
capi->DeltaType = &PyDateTime_DeltaType;
6491+
capi->TZInfoType = &PyDateTime_TZInfoType;
6492+
capi->Date_FromDate = new_date_ex;
6493+
capi->DateTime_FromDateAndTime = new_datetime_ex;
6494+
capi->Time_FromTime = new_time_ex;
6495+
capi->Delta_FromDelta = new_delta_ex;
6496+
capi->TimeZone_FromTimeZone = new_timezone;
6497+
capi->DateTime_FromTimestamp = datetime_fromtimestamp;
6498+
capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi;
6499+
capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2;
6500+
capi->Time_FromTimeAndFold = new_time_ex2;
6501+
// Make sure this function is called after PyDateTime_TimeZone_UTC has
6502+
// been initialized.
6503+
assert(PyDateTime_TimeZone_UTC != NULL);
6504+
capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref
6505+
return capi;
6506+
}
6507+
6508+
static void
6509+
datetime_destructor(PyObject *op)
6510+
{
6511+
void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME);
6512+
PyMem_Free(ptr);
6513+
}
64966514

64976515
static int
64986516
_datetime_exec(PyObject *module)
@@ -6581,7 +6599,6 @@ _datetime_exec(PyObject *module)
65816599
}
65826600

65836601
PyDateTime_TimeZone_UTC = x;
6584-
CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC;
65856602

65866603
/* bpo-37642: These attributes are rounded to the nearest minute for backwards
65876604
* compatibility, even though the constructor will accept a wider range of
@@ -6619,8 +6636,13 @@ _datetime_exec(PyObject *module)
66196636
return -1;
66206637
}
66216638

6622-
x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
6639+
PyDateTime_CAPI *capi = get_datetime_capi();
6640+
if (capi == NULL) {
6641+
return -1;
6642+
}
6643+
x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor);
66236644
if (x == NULL) {
6645+
PyMem_Free(capi);
66246646
return -1;
66256647
}
66266648

0 commit comments

Comments
 (0)
0