correctly registering a plugin to use Eigen via Rcpp

偶尔善良 提交于 2019-12-13 14:35:11

问题


I'm trying to be able to use a c++ class template in R. This was my first try at a small reproducible example.

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))

How to I get access to the Eigen headers, though?

On my machine they are at /usr/include/eigen3/. I think I need to "register a plugin." I'm not sure where this file path goes in. I've tried a few of the named arguments, but no luck. Here's one example of something that I've tried that doesn't work:

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")

I know there is an RcppEigen library that already exists, that would help with this example. If it's possible, I would like to see an answer that doesn't make use of this, though, because the information will be more applicable to other situations where this isn't available. Also, where do you put the c++11 flags? Apparently you can only use cxxfunction with one plugin at a time.

Edit:

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


回答1:


Several comments:

  1. I would use Rcpp::cppFunction instead of inline::cxxfunction.
  2. As Dirk noted in the comments, why are you not using RcppEigen? In particular for Rcpp::as<Eigen::...> you will need that package anyway.
  3. It is possible to create such a plugin on the fly, but setting include paths is a bit more complicated (see example below).
  4. What are you trying to achieve? R won't know what to do with an instance of SillyWrapper.

Example, where I have used some code from the Eigen documentation due to point 4. above:

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;
}'

Let's compile and run this code using the infrastructure provided by RcppEigen:

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

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

And now with our own plugin:

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

Created on 2019-09-04 by the reprex package (v0.3.0)

So while it is in principle possible to write an on-the-fly plugin for a system installed Eigen library, I am unsure how useful that would be given that RcppEigen exists.



来源:https://stackoverflow.com/questions/57778952/correctly-registering-a-plugin-to-use-eigen-via-rcpp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!