c++ - (boost.python) 暴露重载的 operator+() 时出错。 "TypeError: No to_python (by-value) converter found"

标签 c++ python boost boost-python

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

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

现在定义了下面的宏来为两个可能的维度做同样的工作

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“表达式对象”(代表运算符的私有(private)类型)。这是:

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<DIM>::sum 以来,这工作正常并且按照我的意愿进行返回 DIM::Vector .问题是几乎每个被 Eigen 重载的运算符都会返回一个表达式对象,这意味着我必须为几乎所有运算符实现类似的函数!那既不好也不实用:P。

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

最佳答案

似乎矩阵/vector 库正在使用表达式模板。在这种情况下,正如您所说,operator+不返回 vector ,而是返回表示操作的私有(private)类型。返回值被困在 C++ 端,不能传递给 Python,因为私有(private)类型没有注册。

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

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

关于c++ - (boost.python) 暴露重载的 operator+() 时出错。 "TypeError: No to_python (by-value) converter found",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7728382/

相关文章:

boost::asio::basic_socket_acceptor::async_accept() 的接受处理程序中的 C++ boost::asio Variadic 模板运算符

c++ - 使用没有逻辑的删除

c++ - 在 openCV 中为 oclMat 添加小图像到大图像

python - 如何检查列表中的值是否为字符串?

Python在线抓取数据,但csv文件未显示正确的数据格式

c++ - 在 C++ 中为循环编写迭代器的更好方法是什么

c++ - 使用带有 boost::transform_iterator 的状态保存仿函数

c++ - 类主体之外的模板定义

c++ - 为什么 gcc 警告 decltype(main()) 而不是 clang?

python - 全部大写的驼峰式字符串