Python C Api - Function Overloading
I have a number of C functions that accept different arguments, e.g. foo_i(int a) foo_c(char c) Is it possible to overload these functions in python C api? I tried to use the fol
Solution 1:
Either give them different Python level names, or write a single wrapper function that type checks the argument provided and dispatches to the correct "real" function. Python itself has no direct support for overloading functions based on argument types.
If you want the wrapper written for you, you might take a look at pybind11
, which does allow overloading in the sense you're attempting (it does so via a type checking wrapper under the hood, so it's just syntactic sugar, not a change in behavior).
Untested example code:
static PyObject*
foo_wrapper(PyObject *self, PyObject *arg)
{
Py_buffer view;
Py_ssize_t ival;
// Check for/handle length 1 bytes-like object (bytes, bytearray, small mmap, etc.)if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) == 0) {
if (view.len != 1) {
PyErr_Format(PyExc_ValueError, "Must receive exactly one byte, got %zd", view.len);
PyBuffer_Release(&view);
returnNULL;
}
foo_c(((char*)view.buf)[0]);
Py_RETURN_NONE; // Or convert return from foo_c if it exists
}
// Check for/handle integer-like object that fits in C int
PyErr_Clear(); // Ignore error for objects not supporting buffer protocol
ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
// Replace with general error message about both accepted argument types,// since only reporting error from int conversion might confuse folks
PyErr_Format(PyExc_TypeError, "Argument must be length 1 bytes-like object or integer; received %R", Py_TYPE(arg));
}
returnNULL;
}
// Check valid range (Py_ssize_t often larger than int)if (ival < INT_MIN or ival > INT_MAX) {
return PyErr_Format(PyExc_ValueError, "Integer must be in range [%d-%d]; received %zd", INT_MIN, INT_MAX, ival);
}
foo_i((int)ival);
Py_RETURN_NONE; // Or convert return from foo_i if it exists
}
static PyMethodDef test_methods[] = {
{"foo", (PyCFunction)foo_wrapper, METH_O, "Wrapper for foo_c and foo_i"},
{NULL, NULL, 0, NULL}
};
Post a Comment for "Python C Api - Function Overloading"