通过Rcpp正确注册插件以使用Eigen

3

我想能够在R中使用c++类模板。这是我的第一次尝试,提供了一个小的可重现示例。

library(inline)
library(Rcpp)
inc <- 
"#include <Eigen/Dense>

template <size_t dim>
class SillyWrapper  
{
public:
  Eigen::Matrix<double,dim,1> m_vec;
  SillyWrapper(const Eigen::Matrix<int,dim,1>& vec) : m_vec(vec);
};"
src <- 
'SillyWrapper mything(Rcpp::as<Eigen::Map<Eigen::Matrix<double,dim,1>>>(x));'

library(inline)
fun <- cxxfunction(signature(x="numeric"),
                   body=src, 
                   includes=inc, 
                   plugin="Rcpp")
fun(rnorm(3))

如何访问Eigen头文件?

在我的机器上,它们位于/usr/include/eigen3/。我认为我需要“注册一个插件”。我不确定这个文件路径要放在哪里。我尝试过一些命名参数,但是没有成功。以下是一个我尝试过但无法工作的示例:

library(inline)
library(Rcpp)
inc <- 
'template <size_t dim>
class SillyWrapper  
{
public:
  Eigen::Matrix<double,dim,1> m_vec;
  SillyWrapper(const Eigen::Matrix<int,dim,1>& vec) : m_vec(vec);
};'
src <- 
    'SillyWrapper mything(Rcpp::as<Eigen::Map<Eigen::Matrix<double,dim,1>>>(x));'
plug <- Rcpp.plugin.maker(include.before = "#include <Eigen/Dense>", 
                          LinkingTo = "-I/usr/include/eigen3/") # correct arg name?
inline::registerPlugin("eigenDemo", plug)
fun <- cxxfunction(signature(x="numeric"),
                   body=src, 
                   includes=inc, 
                   plugin="eigenDemo")

我知道已经存在一个名为RcppEigen的库,可以帮助解决这个例子。如果可能的话,我希望看到一种不使用它的答案,因为这将更适用于其他没有该库的情况。此外,你在哪里放置c++11标志?显然,你只能一次使用一个插件来使用。

编辑:

谢谢@RalfStubner。对于那些感兴趣的人,我已经发布了一个后续问题here


为什么不使用RcppEigen?只需声明LinkingTo: RcppEigen,R会自动帮你找到头文件。 - Dirk Eddelbuettel
但如果你觉得你更喜欢重复发明轮子: 当然没问题。你需要编写configure逻辑和其他任何尝试确保其所需资源存在的软件包一样。 - Dirk Eddelbuettel
1个回答

5

几点评论:

  1. 我建议使用 Rcpp::cppFunction 而不是 inline::cxxfunction
  2. 正如 Dirk 在评论中指出的那样,为什么不使用 RcppEigen?特别是对于 Rcpp::as<Eigen::...>,您无论如何都需要该软件包。
  3. 可以动态地创建此类插件,但是设置包含路径要复杂一些(请参见下面的示例)。
  4. 你想实现什么目标?R不知道如何处理 SillyWrapper 的实例。

示例,其中我使用 Eigen 文档中的一些代码来解释上述第4点:

src <- '
void foo() {
  Eigen::MatrixXd m(2,2);
  m(0,0) = 3;
  m(1,0) = 2.5;
  m(0,1) = -1;
  m(1,1) = m(1,0) + m(0,1);
  Rcpp::Rcout << "Here is the matrix m:\\n" << m << std::endl;
}'

使用RcppEigen提供的基础设施编译并运行此代码:

Rcpp::cppFunction(code = src,
                  depends = "RcppEigen",
                  includes = "#include <Eigen/Dense>")

foo()
#> Here is the matrix m:
#>   3  -1
#> 2.5 1.5

现在使用我们自己的插件:

Rcpp::registerPlugin(
    name = "Eigen3",
    plugin = function(x) {
        plug <- Rcpp::Rcpp.plugin.maker(include.before = "#include <Eigen/Dense>")
        settings <- plug()
        settings$env$PKG_CPPFLAGS = "-I/usr/include/eigen3"
        settings
    }
)

Rcpp::cppFunction(code = src,
                  plugins = "Eigen3")

foo()
#> Here is the matrix m:
#>   3  -1
#> 2.5 1.5

reprex包 (v0.3.0)于2019年9月4日创建

因此,虽然原则上可以为安装的Eigen库编写即时插件,但考虑到RcppEigen的存在,我不确定这样做有多大用处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接