It looks like C code in Python C-API returns ptr to stack variable. What am I missing?
-
07-06-2021 - |
Question
I was reading through the file methodobject.c, because I'm trying to learn about making C extensions for Python, when I saw the following code snippet:
PyObject *
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyCFunctionObject* f = (PyCFunctionObject*)func;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
Py_ssize_t size;
switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
case METH_VARARGS:
if (kw == NULL || PyDict_Size(kw) == 0)
return (*meth)(self, arg);
break;
The more I look at
return (*meth)(self, arg);
the more I realize I don't understand it. I think it's returning a pointer to meth, which is a function that takes self (a locally declared pointer) and arg (a pointer passed externally into PyCFunctionCall). However, since it looks to me as though meth & self are allocated on the stack, once PyCFunctionCall exits, they will be freed, which will cause problems for whatever variables they are passed to.
What am I missing here?
La solution
It's returning the return value of meth(self, arg)
, not meth
itself. Note that it's derferencing the pointer with (*meth)
, then passing in self
and arg
to the function at that location.
So meth(self, arg)
will be completely evaluated before the return
happens, and no stack variables will be returned.
Edit: when I say meth(self, arg)
, I mean the_function_pointed_to_by_meth(self, arg)
.
Autres conseils
meth
is a function pointer. It's returning the result of the function at *meth
(the address pointed by meth) with the arguments: (self, arg)
;
(*meth)(self, arg)
is a function call.
It just so happens that the function pointer is a local variable. The return
merely passes on whatever comes back from the call.
Function pointer syntax is confusing. :)