Python C api - 函数重载

标签 python overloading python-c-api

我有许多接受不同参数的 C 函数,例如

foo_i(int a)

foo_c(char c)

是否可以在 python C api 中重载这些函数?

我尝试使用以下方法表:

static PyMethodDef test_methods[] = {
    {"foo", (PyCFunction)foo_i, METH_VARARGS, "int"},
    {"foo", (PyCFunction)foo_c, METH_VARARGS, "char"},
    {NULL, NULL, 0, NULL}
};

但是当我从 python 调用 foo 时,我总是最终使用表格底部的函数。

关于如何在 python C-api 中使用 foo() 调用 foo_i()foo_c() 有什么想法吗?

谢谢!

最佳答案

要么给它们不同的Python级别名称,要么编写一个包装函数,对提供的参数进行类型检查并分派(dispatch)到正确的“真实”函数。 Python 本身不直接支持基于参数类型的重载函数。

如果您想要为您编写的包装器,您可以看看pybind11,它确实允许您尝试的意义上的重载(它通过引擎盖下的类型检查包装器来实现) ,所以这只是语法糖,而不是行为的改变)。

未经测试的示例代码:

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);
             return NULL;
        }
        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));
        }
        return NULL;
    }

    // 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}
};

关于Python C api - 函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56042357/

相关文章:

c++ - 将 python + numpy 代码嵌入到 C++ dll 回调中

python - makecython++导致 fatal error : Python. h:尽管安装了python3-dev,但没有这样的文件或目录

Python C API 不加载模块

python - 使用字符串和(填充的)数字格式化字符串

c++ - 什么是 std::map<K,V>::map;以及如何知道在实现/使用 STL 容器和函数时使用什么命名空间?

java - 引用的类类型和实际的类类型,哪个决定调用哪个方法?

带重载的 Java 函数调用

Python配置库

python - 增加数据库中的 IntegerField 计数器

python - 如何在 Pandas 中创建叠加条形图