我正在使用Boost.Python包装C++库。其中的某些函数返回Eigen::MatrixXd对象(dynamically sized double-precision matrix class)。在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()))
        // ...
;

问题是我无法弄清楚该函数的正确签名是什么。 “操作上”应采用两个整数索引并返回一个 double 值。然而,
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的一天。我尝试了typedef -s的各种组合,带有或不带有const限定词。

甚至试图声明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,as documented here之前将EIGEN_DEFAULT_DENSE_INDEX_TYPE定义为int,请注意,这会破坏ABI兼容性。

10-07 12:32
查看更多