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, обращаясь к ее имени:

 caller_cpp(1:3, "fun1_cpp") 

или

 caller_cpp(1:3, "fun2_cpp") 

и т.п.

Вот моя наивная попытка для функции звонящего, которая даже не скомпилируется:

 ## ----------- C++ version ----------- library(Rcpp) require( RcppArmadillo ) sourceCpp( code = ' // [[Rcpp::depends("RcppArmadillo")]] #include  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(funname); if (fstr == "fun1") return(Rcpp::XPtr(new funcPtr(&fun1_cpp))); else if (fstr == "fun2") return(Rcpp::XPtr(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); } ') 

Изменить : адаптировало пример после того, как вы предложили Dirk посмотреть RcppDE.

(Иногда вам нужно использовать svn log ... в файлах, чтобы узнать, насколько они датированы …)

Я думаю, что лучший вариант использования – это мой «порт» на основе D-кода на основе R на Rcpp / RcppArmadillo: RcppDE. В нем я разрешаю подпрограмме оптимизации использовать либо функцию R (как DEoptim), либо предоставленную пользователем скомпилированную функцию – вот что вы хотите здесь, насколько я ее понимаю.

Существует небольшая часть лесов C ++, но после этого у вас не должно возникнуть никаких проблем.

Изменить в 2013-01-21 Ниже представлено полное решение, которое я также выслал как новый пост в галерее Rcpp, включая некоторые комментарии и примеры использования.

 // [[Rcpp::depends(RcppArmadillo)]] #include  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 putFunPtrInXPtr(std::string fstr) { if (fstr == "fun1") return(XPtr(new funcPtr(&fun1_cpp))); else if (fstr == "fun2") return(XPtr(new funcPtr(&fun2_cpp))); else return XPtr(R_NilValue); // runtime error as NULL no XPtr } // [[Rcpp::export]] vec callViaString(const vec x, std::string funname) { XPtr xpfun = putFunPtrInXPtr(funname); funcPtr fun = *xpfun; vec y = fun(x); return (y); } // [[Rcpp::export]] vec callViaXPtr(const vec x, SEXP xpsexp) { XPtr xpfun(xpsexp); funcPtr fun = *xpfun; vec y = fun(x); return (y); } 
Давайте будем гением компьютера.