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

correctly registering a plugin to use Eigen via Rcpp

我正尝试在 R 中使用 c++ class 模板。这是我第一次尝试一个可重现的小例子。

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 headers?

在我的机器上,它们位于 /usr/include/eigen3/。我想我需要 "register a plugin." 我不确定这个文件路径的位置。我已经尝试了一些命名参数,但没有成功。这是我尝试过但不起作用的一个示例:

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 标志放在哪里?显然你一次只能使用一个插件 cxxfunction

编辑:

谢谢@RalfStubner. For those interested, I have posted a follow-up question here

几条评论:

  1. 我会使用 Rcpp::cppFunction 而不是 inline::cxxfunction
  2. 正如德克在评论中指出的那样,您为什么不使用 RcppEigen?特别是 Rcpp::as<Eigen::...> 无论如何你都需要那个包。
  3. 可以即时创建这样的插件,但设置包含路径有点复杂(请参见下面的示例)。
  4. 你想达到什么目的? R 不知道如何处理 SillyWrapper.
  5. 的实例

示例,由于上面的第 4 点,我使用了 Eigen 文档中的一些代码:

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 package (v0.3.0)

于 2019-09-04 创建

因此,虽然原则上可以为系统安装的 Eigen 库编写一个动态插件,但我不确定如果 RcppEigen 存在,它会有多大用处。