在 C++ 中对 PyObject 调用"+="
Call `+=` on a PyObject in C++
我正在用C++编写一个Python模块。
在某个时候,我需要将任意类型的PyObject
添加到另一个。换句话说,做a += b
在Python中所做的同样的事情。但是我无法在 API 中找到执行此操作的函数。
我尝试执行以下操作,
PyObject* increment(PyObject* a, PyObject* b) {
const auto tp = Py_TYPE(a);
[&]{
if (const auto nb = tp->tp_as_number)
if (auto iadd = nb->nb_inplace_add)
return iadd;
if (const auto sq = tp->tp_as_sequence)
if (auto iadd = sq->sq_inplace_concat)
return iadd;
throw error(PyExc_TypeError,
"type "s+(tp->tp_name)+" does not provide __iadd__");
}()(a,b);
return a;
}
但发现 Python 既没有float
,也没有int
,也没有str
实现这些方法。
API 中是否有应用通用+=
的函数?如果没有,我该怎么写?
在某个时候,我需要将任意类型的 PyObject 添加到另一个 PyObject 中。换句话说,做与 += b 在 Python 中所做的相同操作。但是我无法在 API 中找到执行此操作的函数。
您找不到的功能是PyNumber_InPlaceAdd
.
x += y
在 Python 级别相当于
sum = PyNumber_InPlaceAdd(x, y);
Py_DECREF(x);
x = sum;
在 C 级别。(如果需要,还可以同时保留sum
和x
,这对于异常处理非常有用。
PyNumber_InPlaceAdd
处理+=
的完整调度逻辑,包括__iadd__
、双方的__add__
方法(按正确的顺序(、NotImplemented
哨兵和nb_inplace_add
、nb_add
、sq_inplace_concat
和sq_concat
C级钩子。
我最终做了这样的事情:
static PyObject* increment(PyObject*& a, PyObject* b) {
const auto tp = Py_TYPE(a);
if (const auto nb = tp->tp_as_number) {
if (auto iadd = nb->nb_inplace_add)
return iadd(a,args), a;
if (auto add = nb->nb_add)
return a = add(a,b);
}
if (const auto sq = tp->tp_as_sequence) {
if (auto iadd = sq->sq_inplace_concat)
return iadd(a,b), a;
if (auto add = sq->sq_concat)
return a = add(a,b);
}
throw error(PyExc_TypeError,
"cannot increment "s+(tp->tp_name)+" by "+(Py_TYPE(b)->tp_name));
}
正如让-弗朗索瓦·法布尔所建议的那样,如果没有__iadd__
,那就是__add__
。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用