【发布时间】:2020-03-23 09:24:46
【问题描述】:
我正在尝试重载一个 python 扩展函数,该函数将接受一个对象或一个字符串。
typedef struct
{
PyObject_HEAD
} CustomObject;
PyObject* customFunction(CustomObject* self, PyObject* args);
PyMethodDef methods[] =
{
{"customFunction", (PyCFunction) customFunction, METH_VARAGS, "A custom function"},
{NULL}
}
PyTypeObject TypeObj =
{
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "customModule.CustomObject",
.tp_doc = "Custom Object",
.tp_basicsize = sizeof(CustomObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_methods = methods,
}
// Area of problem
PyObject* customFunction(CustomObject* self, PyObject* args)
{
const char* string;
PyObject* object;
if (PyArg_ParseTuple(args, "O!", &TypeObj, &object)) // TypeObj is the PyTypeObject fpr CustomObject
{
std::cout << "Object function\n"
// Do whatever and return PyObject*
}
else if (PyArg_ParseTuple(args, "s", &string))
{
std::cout << "String function\n"
// Do whatever and return PyObject*
}
return PyLong_FromLong(0); // In case nothing above works
}
在 python 中,我尝试了除函数之外的其他方法,但出现此错误Error: <built-in method customFunction of CustomModule.CustomObject object at 0xmemoryadress> returned a result with an error set
这里是这个 PyArg_ParseTuple 的 Python 文档:
int PyArg_ParseTuple(PyObject *args, const char *format, ...)
将只接受位置参数的函数的参数解析为局部变量。成功返回真;失败时,它返回 false 并引发相应的异常
我猜 PyArg_ParseTuple 设置了一个错误,这导致整个函数无法工作(我的模块方法表中确实有 customFunction,我只是省略了该代码)。如果我有以下 Python:
import CustomModule
try:
CustomModule.customFunction("foo")
except Exception as e:
print("Error:", e)
String function 确实被输出了,所以字符串 if 语句中的代码确实有效,但我认为发生错误是因为对象的 PyArg_ParseTuple 失败,所以它返回一个错误(不是 100% 确定这是否正确)。
有什么方法可以防止 PyArg_ParseTuple() 引发错误,是否有其他函数,或者是否有更好的方法来“重载”我的自定义函数?
【问题讨论】:
-
“失败时,它返回 false 并引发适当的异常”——你可以在 Python 中做到这一点吗?今天我学会了。引发异常并返回一个值。有趣。
-
请提供minimal reproducible example。你还没有向我们展示
TypeObj是如何实例化的 -
@JesperJuhl:据我了解,这类似于使用错误代码。例如,
PyErr_SetString -
@JesperJuhl
PyArg_ParseTuple是一个 C 函数。如果出现问题,它会返回一个 C 0 值,然后设置 Python 异常状态。这不是你可以在 Python 中做的事情 - 这就是 Python 异常在 C 中实现的方式。 -
@DavidW 谢谢你的解释。
标签: python c++ overloading cpython python-c-api