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))
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.
Several comments:
Rcpp::cppFunction
instead of inline::cxxfunction
.Rcpp::as<Eigen::...>
you will need that package anyway.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.