RcppArmadillo传递用户定义的函数

考虑下面的R代码,

## ----------- R version ----------- caller <- function(x=1:3, fun = "identity", ...){ ## do some other stuff ## ... ## then call the function eval(call(fun, x)) } fun1 <- function(x, ...){ x + x } fun2 <- function(x, a = 10) a * x caller(fun = "fun1") caller(fun = "fun2") 

用户可以传递函数名称“fun”,这是由caller使用的。 我希望用RcppArmadillo对象执行相同的任务(显然,作为更复杂任务的一部分)。 函数将在C++定义,用户通过引用其名称在R级select它:

 caller_cpp(1:3, "fun1_cpp") 

要么

 caller_cpp(1:3, "fun2_cpp") 

等等

这是我对调用者函数的天真尝试,甚至无法编译:

 ## ----------- C++ version ----------- library(Rcpp) require( RcppArmadillo ) sourceCpp( code = ' // [[Rcpp::depends("RcppArmadillo")]] #include <RcppArmadillo.h> using namespace arma ; using namespace Rcpp ; colvec fun1_cpp(const colvec x) { colvec y ; y = x + x; return (y); } colvec fun2_cpp(const colvec x) { colvec y ; y = 10*x; return (y); } // mysterious pointer business in an attempt // to select a compiled function by its name typedef double (*funcPtr)(SEXP); SEXP putFunPtrInXPtr(SEXP funname) { std::string fstr = Rcpp::as<std::string>(funname); if (fstr == "fun1") return(Rcpp::XPtr<funcPtr>(new funcPtr(&fun1_cpp))); else if (fstr == "fun2") return(Rcpp::XPtr<funcPtr>(new funcPtr(&fun2_cpp))); } // [[Rcpp::export]] colvec caller_cpp(const colvec x, character funname) { Rcpp::XPtr fun = putFunPtrInXPtr(funname); colvec y ; y = fun(x); return (y); } ') 

编辑 :在遵循德克的build议看RcppDE后改编的例子。

(有时候你需要使用svn log ...来查看文件的年代…)

我认为一个更好的用例是在我的基于C的DEoptim到Rcpp / RcppArmadillo:RcppDE的“端口”中。 其中,我允许优化例程使用R函数(如DEoptim所做的)或用户提供的编译函数 – 这正是我所了解的。

有一点C ++脚手架,但你应该没有问题。

编辑于2013年1月21日下面是一个完整的解决scheme,我也张贴在Rcpp画廊张贴这个新的职位 – 包括一些意见和样本用法。

 // [[Rcpp::depends(RcppArmadillo)]] #include <RcppArmadillo.h> using namespace arma; using namespace Rcpp; vec fun1_cpp(const vec& x) { // a first function vec y = x + x; return (y); } vec fun2_cpp(const vec& x) { // and a second function vec y = 10*x; return (y); } typedef vec (*funcPtr)(const vec& x); // [[Rcpp::export]] XPtr<funcPtr> putFunPtrInXPtr(std::string fstr) { if (fstr == "fun1") return(XPtr<funcPtr>(new funcPtr(&fun1_cpp))); else if (fstr == "fun2") return(XPtr<funcPtr>(new funcPtr(&fun2_cpp))); else return XPtr<funcPtr>(R_NilValue); // runtime error as NULL no XPtr } // [[Rcpp::export]] vec callViaString(const vec x, std::string funname) { XPtr<funcPtr> xpfun = putFunPtrInXPtr(funname); funcPtr fun = *xpfun; vec y = fun(x); return (y); } // [[Rcpp::export]] vec callViaXPtr(const vec x, SEXP xpsexp) { XPtr<funcPtr> xpfun(xpsexp); funcPtr fun = *xpfun; vec y = fun(x); return (y); }