简体   繁体   English

Python C ++ API-使用可变数量的参数重载函数

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

I am trying to overload the following sayHi function, that is meant to receive a char* as input argument, or, alternatively, a char* and an integer. 我正在尝试重载以下sayHi函数,该函数旨在接收char *作为输入参数,或者接收char *和一个整数。

It is part of class Box (which itself is used to define the python object PyBox ): 它是Box类的一部分(它本身用于定义python对象PyBox ):

class Box {
   public:

   Box();

   void sayHi(char *name);

   void sayHi(char *name, int number);
   };

In my wrapper, I have defined the following methods: 在包装器中,我定义了以下方法:

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!\n\n");

        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!\n\n");

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

However, when I go to python 3.7 and I run: 但是,当我转到python 3.7并运行时:

bo.Hi("John", 52364)

bo.Hi("Steve")

it prints the first statement but segfaults on Steve. 它输出第一个语句,但在Steve上出现段错误。 Any suggestions why this is the case? 有什么建议为什么会这样?

Thanks! 谢谢!

Problem is here: 问题在这里:

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

if (PyUnicode_Check(x) && PyLong_Check(y)) ...

You're taking two optional parameters (PyArg_ParseTuple does not modify the passed variables if no parameter is given). 您将使用两个可选参数(如果没有给出参数,PyArg_ParseTuple不会修改传递的变量)。 So bo.Hi("Steve") only populates x, but then you use y without checking it, thus the segfault. 因此bo.Hi("Steve")仅填充x,但是随后您使用y而不检查它,因此出现了段错误。 You must have been getting lucky with previous versions on the initial value of y. 您一定已经对使用y的初始值的早期版本感到幸运。

This fixes the issue (see answer by @gct to understand why): 这可以解决问题(请参阅@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!\n\n");

    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!\n\n");

    char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x)); 

    Py_DECREF(x);

    return pyBox_sayHi_char(self, s);
}
else
{
    Py_RETURN_NOTIMPLEMENTED;
}
Py_RETURN_NOTIMPLEMENTED;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM