0
votes

I have a C++ class that contains two overloaded methods sayHi(), each with a different return type:

class Box {
   public:

      Box();

      void sayHi(char *name);

      int sayHi(int number);

};

When I tried to wrap this functions, I followed the suggestion by ShadowRanger and "write a single wrapper function that type checks the argument provided and dispatches to the correct 'real' function".

Here it is:

static PyObject *pyBox_sayHi_char(PyBox *self, char *Name)
{
    self->bx->sayHi(Name);

    Py_RETURN_NONE;
}

static int *pyBox_sayHi_int(PyBox *self,  int number)
{
    int answer;

    answer = self->bx->sayHi(number);

    return answer;
}

static PyObject *Hi_overload_switch(PyBox *self,  PyObject *args)
{
    PyObject *x;

    if (!PyArg_ParseTuple(args, "O", &x))
        return NULL;

    if (PyUnicode_Check(x))
    {
        const char* s = PyBytes_AsString(PyUnicode_AsUTF8String(x)); // convert PyObject to char*

        Py_DECREF(x);

        return pyBox_sayHi_char(self, s);
    }
    if (PyLong_Check(x))
    {   
        return pyBox_sayHi_int( self, PyLong_AsLong(x) );
    }
    Py_RETURN_NOTIMPLEMENTED;
}

and the following methods table:

static PyMethodDef pyBox_methods[] = {
    {"Hi", (PyCFunction)Hi_overload_switch, METH_VARARGS, "Hi"},
    {NULL, NULL, 0, NULL}
};

However, I am getting the error:

error: cannot convert ‘int*’ to ‘PyObject*’ {aka ‘_object*’} in return
         return pyBox_sayHi_int( self, PyLong_AsLong(x) );

AFAIK, I don't want to convert the return types into PyObjects, since the overloaded methods might need to return custom types. Therefore the int vs void in my example is just for illustration purposes - I might well have written PyBanana vs PyOrange data types.

My question is, how do I make the function Hi_overload_switch return different types?

Thanks!

1

1 Answers

1
votes

You need to return a Python int. In C/C++ source this is a PyLongObject (Which is a subtype of PyObject, so you can cast a PyLongObject* to a PyObject* and back). To convert a C++ int into a PyObject* Python int, use PyObject* PyLong_FromLong(long):

static PyObject *pyBox_sayHi_int(PyBox *self,  int number)
{
    int answer;

    answer = self->bx->sayHi(number);

    return PyLong_FromLong(answer);
}