通过 C++ pythonization 回调将 operator() 的 cppyy 自动映射恢复到 __getitem__
Posted
技术标签:
【中文标题】通过 C++ pythonization 回调将 operator() 的 cppyy 自动映射恢复到 __getitem__【英文标题】:Revert cppyy automatic mapping of operator() to __getitem__ via C++ pythonization callback 【发布时间】:2021-02-17 13:56:18 【问题描述】:正如this cppyy issue 中所解释的,C++ 端的A& operator()
映射到python __getitem__
。
如果这不是想要的结果,建议添加一个特殊的pythonization。
在我的例子中,一个额外的限制是将它添加到 C++ 类本身,以确保始终应用这个 python 化。
但是,我无法弄清楚如何通过 Python C API 正确执行此操作。 (第一次使用该 API,所以我有点迷茫)
Minimal Reproducer 有点做作,但显示了问题:注意在下面的示例中,struct A
是我无法修改的代码,因为该类是在库代码中定义的。所以回调必须在B中。
import cppyy
cppyy.include("Python.h")
cppyy.cppdef(r"""
void myprint(PyObject* py)
PyObject* tmp = PyObject_Str(py);
Py_ssize_t size = 0;
const char* s = PyUnicode_AsUTF8AndSize(tmp, &size);
std::cout << std::string(s, size) << std::endl;
template <typename T>
struct A
T& operator[](size_t idx) return arr[idx];
const T& operator[](size_t idx) const return arr[idx];
std::array<T, 10> arr;
;
template <typename T>
struct B : public A<T>
B& operator()() return *this; ;
static void __cppyy_pythonize__( PyObject* klass, const std::string& name)
std::cout << "Hello from pythonize" << std::endl;
PyObject* getitem = PyObject_GetAttrString(klass, "__getitem__");
myprint(getitem);
;
using tmp = B<double>;
""")
t = cppyy.gbl.B['double']
print(t.__getitem__.__doc__)
我可以从 PyObject* klass
获取 __getitem__
函数,但是,正如文档中所解释的,回调发生在类的所有内部处理之后的最后。
因此__call__
函数,这里是B& operator()()
,已经映射到__getitem__
。
不幸的是,我一生都无法弄清楚如何撤消该映射并取回旧的__getitem__
函数。
operator[]()
功能是否仍然可以通过 PyObject* klass
访问?
任何帮助/指针将不胜感激:)
【问题讨论】:
【参考方案1】:首先,回答你的问题,找到你想要的__getitem__
,从klass
的基类中获取,而不是直接从klass
获取。您也可以在 Python 中执行此操作,而不是在 C++ 中添加 python 化。事实上,最好在 Python 中执行此操作,因为这样您就不必处理 C-API。
但是,由于实际的错误报告不是您引用的错误报告,而是 this one,并且由于您在此处遵循的那里提出的建议使这是一个经典的 XY 问题,所以我还要补充一下您真正的问题想要在你的代码示例中简单地做PyObject_DelAttrString(klass, "__getitem__")
。
完全不说,这里给您带来麻烦的代码来自 Gaudi 项目,该项目的核心开发人员是最开始要求这种自动映射的人。你可能想和他们一起解决这个问题。
【讨论】:
非常感谢 Wim 的快速回复!我想在 C-API 中执行此操作的原因是我没有看到一种使用 Python 全局执行此操作的方法。此外,最后它似乎不是一个复杂的解决方案!只是觉得我现在有更多问题,因为我不清楚为什么会这样 :D 无论如何,再次感谢您抽出时间回复并解决我的问题 :)以上是关于通过 C++ pythonization 回调将 operator() 的 cppyy 自动映射恢复到 __getitem__的主要内容,如果未能解决你的问题,请参考以下文章
将 python 函数传递给 SWIG 包装的 C++ 代码
使用 boost::python 将回调从 python 传递到 c++