繁体   English   中英

使用 Boost.Python 包装 Eigen 的 operator()() 时的重载解析

[英]Overload resolution of Eigen's operator()() when wrapping it with Boost.Python

我正在使用 Boost.Python 包装 C++ 库。 其中的一些函数返回Eigen::MatrixXd对象( 动态大小的双精度矩阵类)。 在 Python 方面,我只需要访问矩阵的维度,这很容易,并使用 Eigen 的重载operator()()方法检索一些矩阵元素。 不幸的是,有 4 个这样的重载方法,一个必须手动选择正确的方法,即给 Boost.Python 一个带有正确签名的函数指针 typedef,类似的东西

namespace bpy = boost::python;
bpy::class_<Eigen::MatrixXd>("MatrixXd",
        "Variable-size double-precision matrix class",
        bpy::init<const Eigen::MatrixXd&>()
    )
        .def("__call__", static_cast<parop_signature>(&Eigen::MatrixXd::operator()))
        // ...
;

问题是我无法弄清楚该函数的正确签名是什么。 “操作上”它应该采用两个整数索引并返回一个双精度值。 然而,

typedef const double& (Eigen::MatrixXd::*parop_signature)(int, int) const;

导致以下编译错误(Mac OS X、C++11 模式下的 clang++、Boost.Python V1.61):

address of overloaded function 'operator()' cannot be static_cast to type
      'const double &(MatrixXd::*)(int, int) const'
  ...static_cast<const double& (Eigen::MatrixXd::*)(int, int) const>(&Eigen::MatrixXd::operator())
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:111:41: note: 
      candidate function
    EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
                                        ^
/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:171:5: note: 
      candidate function
    operator()(Index index) const
    ^
/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:334:5: note: 
      candidate function
    operator()(Index row, Index col)
    ^
/usr/local/eigen/current/Eigen/src/Core/DenseCoeffsBase.h:392:5: note: 
      candidate function
    operator()(Index index)

很公平,你会说:但我不知道如何告诉 Boost.Python CoeffReturnType实际上是一个double (或者可能是const double& ,谁知道?),并且IndexType将解析为一个普通的int一天结束。 我已经尝试了带有或不带有const限定符的typedef -s 的各种组合。

甚至试图声明一个 C++11 风格的函数指针,比如

auto eigen_indexfn = std::mem_fn<double(int,int)>(&Eigen::MatrixXd::operator());

,没有成功,我明白了

candidate template ignored: couldn't infer template argument '_Tp'
mem_fn(_Rp _Tp::* __pm)
^

有没有人已经经历过这个并且可以为我提供正确的签名,说明什么应该像“ double Eigen::MatrixXd::operator(int, int) ”一样简单? 任何提示将不胜感激。

错误似乎源于Eigen::Index不是int但默认为ptrdiff_t 仅仅因为int可以隐式转换为Eigen::Index并不意味着您可以将需要Eigen::Index的函数指针转换为需要int的函数指针。 如果这是可能的,您最终会在堆栈上传递错误大小的整数。

附录:如果您真的更喜欢int不是ptrdiff_t ,您可以在包含 Eigen 之前将EIGEN_DEFAULT_DENSE_INDEX_TYPE定义为int如此处所述,请注意这会破坏 ABI 兼容性。

非常感谢@xao 和@chtz 的帮助。 作为参考(双关语),我在这里展示了最终有效的解决方案,并附有评论。

第一部分,用于访问矩阵元素的 Eigen 括号运算符的签名:

// const element access in dynamically-sized double matrices
// note that the Index type is ptrdiff_t
// and the CoeffReturnType is const double&
typedef const double& (Eigen::MatrixXd::*parop_signature)(ptrdiff_t,ptrdiff_t) const;

第二部分,必须定义适当的退货政策。 我们想使用由operator()()返回的const double&所以策略将是copy_const_reference

bpy::class_<Eigen::MatrixXd>("MatrixXd",
    "Variable-size double-precision matrix class",
    bpy::init<const Eigen::MatrixXd&>()
)
    .def("__call__", static_cast<parop_signature>(&Eigen::MatrixXd::operator()),
        bpy::return_value_policy<bpy::copy_const_reference>())

在完成所有这些之后,它可以编译并且可以从 Python 正确调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM