所以我正在使用 python boost。我的目标是能够从 python 模块重载 c++ 函数。我已经做到了,但在使用别名时我观察到了奇怪的行为。
我重新创建了一个基本示例来重现该错误:
#include <boost/python.hpp>
#include <iostream>
#include <string>
// CppBase class
class CppBase {
public:
CppBase(){}; // Default constructor
virtual std::string myOverridableCallback() {
return "Callback triggered from CppBase"; // Default implementation
}
virtual void display() {
std::cout << "CppBase class display function" << std::endl;
std::cout << this->myOverridableCallback() << std::endl;
}
};
// CppBase class WRAPPER
struct CppBaseWrap : public CppBase, boost::python::wrapper<CppBase> {
public:
virtual std::string myOverridableCallback() override {
// Check if override is provided in Python
if (boost::python::override f =
this->get_override("myOverridableCallback")) {
return f(); // Call the Python version
}
return CppBase::myOverridableCallback(); // Call the Default implementation
}
};
// CppDerived class
class CppDerived : public CppBase {
public:
CppDerived() {} // Default constructor
void show() {
std::cout << "CppDerived class show function" << std::endl;
std::cout << this->myOverridableCallback() << std::endl;
}
};
using CppDerivedCopy = CppDerived;
// CppDerived class WRAPPER
struct CppDerivedWrap : public CppDerived, boost::python::wrapper<CppDerived> {
virtual std::string myOverridableCallback() override {
// Check if override is provided in Python
if (boost::python::override f =
this->get_override("myOverridableCallback")) {
return f(); // Call the Python version
}
return CppBase::myOverridableCallback(); // Call the Default implementation
}
};
BOOST_PYTHON_MODULE(InheritedFunctionTest) {
// Expose the CppBase class
boost::python::class_<CppBaseWrap, boost::noncopyable>("CppBase", boost::python::init<>())
.def("myOverridableCallback", &CppBaseWrap::myOverridableCallback)
.def("display", &CppBase::display);
// Expose the CppDerived class
boost::python::class_<CppDerivedWrap, boost::python::bases<CppBase>, boost::noncopyable>("CppDerived", boost::python::init<>())
.def("myOverridableCallback", &CppDerived::myOverridableCallback)
.def("show", &CppDerived::show);
// Expose the CppDerivedCopy class
boost::python::class_<CppDerivedWrap, boost::python::bases<CppBase>, boost::noncopyable>("CppDerivedCopy", boost::python::init<>())
.def("myOverridableCallback", &CppDerivedCopy::myOverridableCallback)
.def("show", &CppDerivedCopy::show);
}
所以如你所见,我有
using CppDerivedCopy = CppDerived;
。我的想法是能够在 python 中实现 from InheritedFunctionTest import CppDerivedCopy
并具有与 CppDerived
完全相同的行为。
我的代码可以编译,这是我的 python 基本示例:
import sys
sys.path.append('./build')
import InheritedFunctionTest
derived_obj = InheritedFunctionTest.CppDerived()
derived_obj.show() # Calls show from Derived and myCallback from CppBase
derived_obj2 = InheritedFunctionTest.CppDerivedCopy()
derived_obj2.show() # Calls show from Derived and myCallback from CppBase
这将触发以下错误:
Traceback (most recent call last):
File "test_script.py", line 13, in <module>
derived_obj.show() # Calls show from Derived and myCallback from CppBase
RecursionError: maximum recursion depth exceeded while calling a Python object
所以这里
InheritedFunctionTest.CppDerived()
触发了这个错误。这里出现了奇怪的行为,如果在我的 cpp 代码中,我在 CppDerivedCopy
之前暴露了 CppDerived
(因此只需反转 c++ 文件中的最后 2 个代码块),我会遇到相同的错误,但在 InheritedFunctionTest.CppDerivedCopy()
上
对象,并且 InheritedFunctionTest.CppDerived()
对象没有引起任何问题。
因此,两个声明中的最后一个不会有问题,而第一个声明将出现此 RecursionError。
我尝试了很多不同的方法,但我没有找到问题的根源,chatGPT 也没有,谷歌也没有给我太多文档。任何帮助将不胜感激 !! 谢谢
请测试下面提供的修改后的 Boost.Python 代码,看看它是否解决了递归错误。确保使用以下更改替换现有代码:
call
函数中使用 get_override
代替 myOverridableCallback
。virtual std::string myOverridableCallback() override {
namespace bp = boost::python;
bp::object pyOverride = this->get_override("myOverridableCallback");
if (pyOverride) {
return bp::extract<std::string>(pyOverride());
}
return CppBase::myOverridableCallback();
}
// Expose the CppBase class
boost::python::class_<CppBaseWrap, boost::noncopyable>("CppBase", boost::python::init<>())
.def("display", &CppBase::display);
// Expose the CppDerived class
boost::python::class_<CppDerivedWrap, boost::python::bases<CppBase>, boost::noncopyable>("CppDerived", boost::python::init<>())
.def("myOverridableCallback", &CppDerived::myOverridableCallback)
.def("show", &CppDerived::show);
// Expose the CppBase class
boost::python::class_<CppBaseWrap, boost::noncopyable>("CppBase", boost::python::init<>())
.def("display", &CppBase::display)
.def("myOverridableCallback", &CppBase::myOverridableCallback);
// Expose the CppDerived class
boost::python::class_<CppDerivedWrap, boost::python::bases<CppBase>, boost::noncopyable>("CppDerived", boost::python::init<>())
.def("show", &CppDerived::show);