Python C ++ API - перегрузка функций с переменным количеством аргументов - PullRequest
0 голосов
/ 21 мая 2019

Я пытаюсь перегрузить следующую 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!\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}
};

Однако, когда я захожу на python 3.7 и запускаю:

bo.Hi("John", 52364)

bo.Hi("Steve")

, он печатает первое утверждение, но с ошибками на Стиве.Любые предложения, почему это так?

Спасибо!

Ответы [ 2 ]

1 голос
/ 21 мая 2019

Проблема здесь:

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

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

Вы принимаете два необязательных параметра (PyArg_ParseTuple не изменяет переданные переменные, если параметр не указан). Таким образом, bo.Hi("Steve") заполняет только x, но затем вы используете y, не проверяя его, таким образом, это ошибка. Наверное, вам повезло с предыдущими версиями на начальном значении y.

0 голосов
/ 21 мая 2019

Это устраняет проблему (см. Ответ @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;
}
...