Reputation: 1051
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.
It is part of class Box (which itself is used to define the python object 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:
bo.Hi("John", 52364)
bo.Hi("Steve")
it prints the first statement but segfaults on Steve. Any suggestions why this is the case?
Thanks!
Upvotes: 0
Views: 199
Reputation: 1051
This fixes the issue (see answer by @gct to understand why):
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;
}
Upvotes: 1
Reputation: 14583
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). So bo.Hi("Steve")
only populates x, but then you use y without checking it, thus the segfault. You must have been getting lucky with previous versions on the initial value of y.
Upvotes: 2