Python C API-具有可变的参数数量的过载函数

Python C++ API - overloading functions with variable number of arguments

本文关键字:数数 参数 函数 API- Python      更新时间:2023-10-16

我试图超载以下 sayhi 函数,该功能旨在接收一个char*作为输入参数,或或者,char*和一个整数。

它是类的一部分 box (本身用于定义Python对象 PYBOX (:

class Box {
   public:
   Box();
   void sayHi(char *name);
   void sayHi(char *name, int number);
   };

在我的包装器中,我定义了以下方法:

static PyObject *pyBox_sayHi_char(PyBox *self, char *Name)
{
    self->bx->sayHi(Name);
    Py_RETURN_NONE;
}
static PyObject *pyBox_sayHi_char_int(PyBox *self, char *Name, int number)
{
        self->bx->sayHi(Name, number);
    Py_RETURN_NONE;
}
static PyObject *Hi_overload_switch(PyBox *self,  PyObject *args)
{
    PyObject *x = NULL;
    PyObject *y = NULL;
    if (!PyArg_ParseTuple(args, "|OO", &x, &y))
        return NULL;
    if (PyUnicode_Check(x) && PyLong_Check(y) && y != NULL)
    {
        printf("A!nn");
        const char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x)); 
        Py_DECREF(x);
        return pyBox_sayHi_char_int(self, s, PyLong_AsLong(y));
    }
    else if (PyUnicode_Check(x) && y == NULL)
    {   
        printf("B!nn");
        const char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x)); 
        Py_DECREF(x);
        return pyBox_sayHi_char(self, s);
    }
    else
    {
        Py_RETURN_NOTIMPLEMENTED;
    }
    Py_RETURN_NOTIMPLEMENTED;
}
static PyMethodDef pyBox_methods[] = {
    {"Hi", (PyCFunction)Hi_overload_switch, METH_VARARGS, "Hi"},
    {NULL, NULL, 0, NULL}
};

但是,当我进入python 3.7并运行时:

bo.Hi("John", 52364)
bo.Hi("Steve")

它打印了第一个语句,但在史蒂夫(Steve(上segfault。有什么建议为什么是这种情况?

谢谢!

问题在这里:

if (!PyArg_ParseTuple(args, "|OO", &x, &y))
    return NULL;
if (PyUnicode_Check(x) && PyLong_Check(y)) ...

您正在使用两个可选参数(如果没有给出参数,则PYARG_PARSETUPLE不会修改传递的变量(。因此,bo.Hi("Steve")仅填充X,但是您在不检查的情况下使用Y,因此可以使用Segfault。您必须对y。

的初始值进行以前的版本很幸运

这解决了问题(请参阅@GCT的答案以了解原因(:

static PyObject *Hi_overload_switch(PyBox *self,  PyObject *args)
{
PyObject *x = Py_None;
PyObject *y = Py_None;
if (!PyArg_ParseTuple(args, "|OO", &x, &y))
    {return NULL;}
if (PyUnicode_Check(x) && PyLong_Check(y) && y != Py_None)
{
    printf("A!nn");
    char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x));
    Py_DECREF(x);
    return pyBox_sayHi_char_int(self, s, PyLong_AsLong(y));
}
else if (PyUnicode_Check(x) && y == Py_None)
{   
    printf("B!nn");
    char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x)); 
    Py_DECREF(x);
    return pyBox_sayHi_char(self, s);
}
else
{
    Py_RETURN_NOTIMPLEMENTED;
}
Py_RETURN_NOTIMPLEMENTED;
}