Skip to content

Commit 0eeea13

Browse files
committed
ctypes: Return existing pointer when possible
Addresses gh-46376
1 parent 443d9b3 commit 0eeea13

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

Modules/_ctypes/_ctypes.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5129,6 +5129,7 @@ static PyObject *
51295129
Pointer_get_contents(CDataObject *self, void *closure)
51305130
{
51315131
StgDictObject *stgdict;
5132+
PyObject *keep, *pointer_probe, *pointer_to_pointer;
51325133

51335134
if (*(void **)self->b_ptr == NULL) {
51345135
PyErr_SetString(PyExc_ValueError,
@@ -5138,6 +5139,27 @@ Pointer_get_contents(CDataObject *self, void *closure)
51385139

51395140
stgdict = PyObject_stgdict((PyObject *)self);
51405141
assert(stgdict); /* Cannot be NULL for pointer instances */
5142+
5143+
keep = GetKeepedObjects(self);
5144+
if (keep != NULL) {
5145+
// check if it's a pointer to a pointer:
5146+
// pointers will have '0' key in the _objects
5147+
5148+
pointer_probe = PyDict_GetItemString(keep, "0");
5149+
5150+
if (pointer_probe != NULL) {
5151+
pointer_to_pointer = PyDict_GetItemString(keep, "1");
5152+
if (pointer_to_pointer == NULL) {
5153+
PyErr_SetString(PyExc_ValueError,
5154+
"Unexpected NULL pointer in _objets");
5155+
}
5156+
// don't construct a new object,
5157+
// return existing one instead to preserve refcount
5158+
Py_INCREF(pointer_to_pointer);
5159+
return pointer_to_pointer;
5160+
}
5161+
}
5162+
51415163
return PyCData_FromBaseObj(stgdict->proto,
51425164
(PyObject *)self, 0,
51435165
*(void **)self->b_ptr);

0 commit comments

Comments
 (0)