【发布时间】:2019-08-18 16:54:48
【问题描述】:
在 boost-python 中,给定一些类 X,推荐的公开虚拟方法的方法是如下所示包装它。
我正在尝试将此与在该虚拟方法上指定默认参数的功能结合起来。 Boost 文档也支持这一点。
但是没有给出公开一个也有默认参数的虚方法的例子。
我假设包装类还必须将参数定义为默认值,并将其传递给底层getItem()。
默认参数是一个 NULL 指针,尽管我没有理由怀疑(目前)这是相关的。
struct X_wrap : X, wrapper<X>
{
X_wrap(): X() {}
// getItem() is a non-Pure Virtual Function in Class X
// It has a single argument a, which has a default value of 1
A* getItem(Z* a=NULL)
{
if (override getItem = this->get_override("getItem"))
return getItem(a);
return X::getItem(a);
}
A* default_getItem(Z* a=NULL) { return this->X::getItem(a); }
};
然后定义为:
.def("getItem",
&X::getItem,
&X_wrap::default_getItem);
问题是默认参数不会作为方法签名的一部分携带。
Boost 提供了一个解决方法:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getItem_member_overloads, getItem, 0, 1)
在非虚拟情况下很清楚如何将其应用于def:
.def("getItem",
&X::getItem,
getItem_member_overloads());
这会按预期编译和工作。
但是,当我们有一个虚函数时,包装器和默认函数会使事情复杂化,不清楚如何将它们结合起来。我假设上述不是正确的解决方案,因为我已经从定义中删除了default_getItem()。
这导致我尝试创建第二组重载:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(default_getItem_overloads, default_getItem, 0, 1);
宏会编译,但似乎没有办法将 2 组单独的重载应用到 .def(),这样不会导致编译失败。
Google 建议我可以使用 boost::python::arg() 并将其定义为 arg("a")=1:
编译如下:
.def("getItem",
&X::getItem,
arg("a")=0,
&X_wrap::default_getItem,
arg("a")=0);
但我得到一个运行时错误:
Boost.Python.ArgumentError: Python argument types in
X.getItem(ChildClassOfX)
did not match C++ signature:
getItem(X_wrap {lvalue}, Z* a=0)
getItem(X {lvalue}, Z* a=0)
这表明ChildClassOfX 出于某种原因与基类X 中getItem() 的签名不匹配。
在这一点上我有点犹豫 - 我的定义可能是简单明了的错误!
到目前为止,我拥有的任何解决方案要么以某种方式破坏运行时多态性,要么无法编译。
任何建议或示例都会有很大帮助!
(注意 Pure 虚拟函数不需要默认函数意味着只有一个函数被传递到.def(),因此修改非虚拟琐碎示例看起来很简单 -非纯虚拟不是这种情况)
编辑
在网上找到了其他人提出相同问题的单一参考 - 该解决方案与我使用 args 的尝试接近,但似乎不起作用并且违反了当前的 Boost 文档?它对getItem() 和default_getItem() 使用def() 中的包装类,并传入一组参数 - 下面是参考中给出的示例。唯一的其他区别是默认值是一个值而不是我的情况下的指针:
def("override", WrapperClass::func, WrapperClass::default_func, (arg("x"), arg("y")=0, arg("z")=false))
修改我的示例构建正常,但抛出:
Boost.Python.ArgumentError: Python argument types in
X.getItem(ChildClassOfX)
did not match C++ signature:
getItem(X_wrap {lvalue}, Z* a=0)
getItem(X_wrap {lvalue}, Z* a=0)
参考: http://boost.2283326.n4.nabble.com/Boost-Python-inheritance-optional-parameters-td4592869.html
【问题讨论】:
标签: python c++ boost boost-python