Python C++ API - 具有可变数量参数的重载函数
Posted
技术标签:
【中文标题】Python C++ API - 具有可变数量参数的重载函数【英文标题】:Python C++ API - overloading functions with variable number of arguments 【发布时间】:2019-05-21 16:09:43 【问题描述】:我正在尝试重载以下 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")
它打印第一条语句,但在 Steve 上出现了段错误。有什么建议为什么会这样?
谢谢!
【问题讨论】:
Python 版本? 起来! 3.7 版 - 谢谢;编辑了问题 在您的else if (PyLong_Check(x))
中,您正在检查long
,然后将x
转换为字符串...对吗?
很好看!我已经在问题中更正了,但是结果是一样的!
【参考方案1】:
问题就在这里:
if (!PyArg_ParseTuple(args, "|OO", &x, &y))
return NULL;
if (PyUnicode_Check(x) && PyLong_Check(y)) ...
您正在使用两个可选参数(如果没有给出参数,PyArg_ParseTuple 不会修改传递的变量)。所以bo.Hi("Steve")
只填充 x,但是你使用 y 而不检查它,因此是段错误。在 y 的初始值上,您一定很幸运能够使用以前的版本。
【讨论】:
谢谢!那么如何检查传递给 Hi 函数的参数数量? 在这种情况下,我会将它们显式设置为nullptr
,然后在调用 PyArg_ParseTuple
后检查它们是否为空
请注意,PyArg_ParseTuple
不会在您需要保留必须自己做的对象时为您增加引用计数。【参考方案2】:
这解决了问题(请参阅@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;
【讨论】:
以上是关于Python C++ API - 具有可变数量参数的重载函数的主要内容,如果未能解决你的问题,请参考以下文章