【问题标题】:(boost.python) Error exposing overloaded operator+(). "TypeError: No to_python (by-value) converter found"(boost.python) 暴露重载的 operator+() 时出错。 “TypeError:找不到 to_python(按值)转换器”
【发布时间】:2011-10-11 15:19:06
【问题描述】:

我是 boost.python 的新手,我遇到了这个错误,我想得到一些帮助。作为一个更大项目的一部分,我正在为我拥有的向量类编写一个包装器。正如您会从下面的代码中注意到的那样,这个类可以是 2D 或 3D,但对于我目前遇到的问题来说差别不大。我正在尝试包装我拥有的向量类中定义的一些运算符,只要函数(或重载的运算符)不返回 Vector 类型的“值”,它就可以正常工作,所以我猜 python 不知道什么与我按价值返回的对象有关。这是代码:

struct D2
{
   //...
   typedef Eigen::Matrix< long double, 2, 1 > Vector;
   //...
};
struct D3
{
   //...
   typedef Eigen::Matrix< long double, 3, 1 > Vector;
   //...
};

现在定义了以下宏来对 2 个可能的维度执行相同的工作

BOOST_PYTHON_MODULE(types)
{
using namespace boost::python;

#define GPS_PY_EXPOSE_VECTOR(DIM, NAME)                                                 \
        class_<DIM::Vector>(NAME)                                                       \
                .def(init<DIM::Vector>())                                               \
                .def("norm", &DIM::Vector::norm)                                        \
                .def("__setitem__", &PyVectorHelper<DIM>::setVectorElem)                \
                .def("__getitem__", &PyVectorHelper<DIM>::getVectorElem)                \
                .def(self += self)                                                      \
                .def(self -= self)                                                      \
                .def(self + self)   /*Not working!!!*/                                  \
                .def(self - self)   /*Not working!!!*/                                  \
                .def("toStr", &PyVectorHelper<DIM>::toPyString)                         \
                .def("__str__", &PyVectorHelper<DIM>::toStdString)                      \
        ;

GPS_PY_EXPOSE_VECTOR(D2, "Vector2D")
GPS_PY_EXPOSE_VECTOR(D3, "Vector3D")
}

上面的代码可以正常工作,除非我尝试在python中使用“+”或“-”运算符,如下所示:

>>>import types
>>>v1 = types.Vector2D()
>>>v2 = types.Vector2D()
>>>v3 = v1 + v2                //ERROR!!!

错误如下:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No to_python (by-value) converter found for C++ type: Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<long double>, Eigen::Matrix<long double, 2, 1, 0, 2, 1> const, Eigen::Matrix<long double, 2, 1, 0, 2, 1> const>

我按照教程here,在网上没有找到与错误相关的信息。

非常欢迎任何帮助! 提前致谢。

在 Luc Danton 回答后编辑

致 Luc Danton:感谢您的回答,我尝试了您所说的,但没有成功。这是我得到的错误:

error: no matching function for call to ‘boost::python::class_<Eigen::Matrix<long double, 2, 1, 0, 2, 1>, boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::def(boost::python::detail::operator_<(boost::python::detail::operator_id)0u, boost::python::self_ns::self_t, boost::python::self_ns::self_t>, boost::python::return_value_policy<boost::python::to_python_value<Eigen::Matrix<long double, 2, 1, 0, 2, 1> >, boost::python::default_call_policies>)’

但是,感谢您的评论,我有了这个想法:编写一个辅助函数来执行加法并转换 Eigen“表达式对象”(这是表示运算符的私有类型)。这是:

template <typename TDim>
struct PyVectorHelper
{
    //...
    static typename TDim::Vector sum(typename TDim::Vector const &v1, typename TDim::Vector const &v2)
    {
        return v1 + v2;
    }
    //...
};

然后

.def("__add__", &PyVectorHelper<DIM>::sum)

因为PyVectorHelper&lt;DIM&gt;::sum 返回一个DIM::Vector,所以它工作正常并且可以按照我的意愿执行。问题是几乎每个被 Eigen 重载的运算符都返回一个表达式对象,这意味着我必须为几乎所有的运算符实现类似的函数!那既不好也不实用:P。

也许仍然可以使用return_value_policyto_python_value 这样我就可以避免这种繁琐的运算符重写?

【问题讨论】:

    标签: c++ python boost boost-python


    【解决方案1】:

    矩阵/向量库似乎正在使用表达式模板。在这种情况下,正如您所说,operator+ 不是返回一个向量,而是一个表示操作的私有类型。返回的值被困在 C++ 方面,由于未注册私有类型,因此无法传递给 Python。

    现在我对 Boost.Python 不太熟悉,但我认为您可以使用 return value policy 解决您的问题。将return_value_policy&lt;to_python_value&lt;DIM::Vector&gt; &gt; 作为策略传递将强制将返回的类型转换为您已注册的DIM::Vector。这看起来像:

    .def(self + self, return_value_policy<to_python_value<DIM::Vector> >())
    

    【讨论】:

    • 请在您回答后检查我对帖子所做的编辑,字数限制不允许我在这里发表这样的评论。
    • @sinad 不幸的是,进一步查看文档,def 似乎没有过载,它接受运算符表达式(此处为self + self)和策略的结果,因此你正在经历的结果。您的方法在 IMO 非常有效,我会毫不犹豫地使用预处理器为我做一些重复性工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    相关资源
    最近更新 更多