python - CPython 'overloaded' 函数

标签 python c++ overloading cpython python-c-api

我正在尝试重载一个接受对象或字符串的 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, ...)

Parse the parameters of a function that takes only positional parameters into local variables. Returns true on success; on failure, it returns false and raises the appropriate exception

我猜测 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() 引发错误,是否有其他函数,或者是否有更好的方法来“重载”我的自定义函数?

最佳答案

我可能只是使用 PyArg_ParseTuple 来获取通用的未指定对象,然后稍后使用 Py*_Check 处理对象类型:

if (!PyArg_ParseTuple(args, "O", &object)) {
    return NULL;
}
if (PyObject_IsInstance(object, (PyObject*)&PyType)) { // or a more specific function if one exists
    std::cout << "Object function\n";
} else if (PyUnicode_Check(object)) {
    std::cout << "String function\n";
} else {
    // set an error, return NULL
}

这是因为 Python 的“请求原谅,而不是许可”模式

try:
    something()
except SomeException:
    somethingElse()

不能很好地转换为 C,并且涉及相当多的代码来处理异常。如果您真的想那样做,那么您需要在第二个PyArg_ParseTuple 之前调用PyErr_Clear,理想情况下您应该检查它是否是异常思考,而不是完全是别的东西。

关于python - CPython 'overloaded' 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59076682/

相关文章:

python - 菜鸟算法设计

python - 使用 Gmail Python 发送电子邮件

c++ - C++中的重载函数数组

c++ - 模板化运算符实例化和类型转换

python - 如何计算参数的谱范数?

c++ - 如何调试 armv5 上的堆损坏

c++ - 单线程可以双重锁定互斥量吗?

c++ - 如何在宏中排除 lcov 分支

c++ - 哪个是更专业的模板功能? clang 和 g++ 对此有所不同

python - 打印 Boost Python 对象