Python C Extension - Why are methods that use keyword arguments cast to PyCFunction
Asked Answered
P

2

8

I've am learning about Python-C extensions and am puzzled as to why methods that use keyword arguments must be cast to PyCFunctions.

My understanding of a PyCFunction is that it takes two pointers to PyObjects and returns a single pointer to a PyObject - e.g.

 PyObject* myFunc(PyObject* self, PyObject* args)

If I'm going to use a function that uses keyword arguments, then this function will take three pointers to PyObjects and returns a single pointer to a PyObject - e.g.

 PyObject* myFunc(PyObject* self, PyObject* args, PyObject* keywordArgs)

However, when I create the module functions array (for a function called 'adder'):

{ "adder", (PyCFunction)adder, METH_VARARGS | METH_KEYWORDS, "adder method" }

works fine. It feels like I cast a float to an int and still got to use the non-integer parts of the float. If I didn't see this work, I would have thought it wouldn't work. What am I not understanding here?

Also, I saw some references to a PyCFunctionWithKeywords, which seems to have the function signature I thought I needed, but my compiler complained (gave warnings) about 'incompatible pointer types'.

Was PyCFunctionWithKeywords deprecated? If not, is there a time when I should/must use it?

Plauen answered 21/4, 2012 at 23:54 Comment(0)
U
5

If your function handles keyword arguments, then it must correspond to a PyCFunctionWithKeywords. However, C doesn’t do overloading, and the structure built by PyMethodDef is defined to expect a PyCFunction, rather than, say, a completely unchecked void *. So you must cast your PyCFunctionWithKeywords to a PyCFunction to stop the compiler complaining, that’s all.

Remember that you must also pass METH_KEYWORDS in the flags to tell Python that your function has the signature of a PyCFunctionWithKeywords, not a PyCFunction.

Unknowable answered 22/4, 2012 at 1:47 Comment(3)
So the METH_KEYWORDS flag tells one of the C routines in the Python interpreter to cast back to PyCFunctionWithKeywords?Plauen
Yes, it's exactly like that (see PyCFunction_Call() here svn.python.org/projects/python/branches/pep-0384/Objects/…).Weevil
C language itself does not promise that a function pointer cast to void* can be successfully cast back to a function pointer.Banns
U
0

D'Olveiro is 100% correct, but (depending on your compiler) you may still get a "cast-function-type" warning, which you can safely ignore. Or (if using a gcc varient) surround with pragma to temporarily turn off that warning:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
static PyMethodDef MyPythonMethods[] = {
    {"myMethod", (PyCFunction)MyMethodFunction, METH_VARARGS, "doc string"},
    ...
    {NULL, NULL, 0, NULL}
};
#pragma GCC diagnostic pop
Upper answered 30/1, 2023 at 22:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.