2013-01-20 9 views
37

は、ユーザが、それはcallerによって使用され、関数名「楽しい」を渡すことができRcppArmadilloユーザ定義関数を渡す

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

、以下のRコードを考えます。 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 <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); 
     } 

    ') 

を編集してください:RcppDEを見るためのDirkの提案に従ってください。

答えて

29

(いつかあなたは、彼らがどのように日付を参照するファイルにsvn log ...を使用する必要があります...)

私はより良いユースケースはRcpp/RcppArmadilloにCベースのDEoptimの私の「ポート」であると思います: RcppDE。その中で、私は最適化ルーチンにR関数(DEoptimのように)またはユーザが提供するコンパイルされた関数を使用することを許可します。

C++の足場はごくわずかですが、それに続く問題はありません。

編集:2013-01-21以下は、私がちょうどthis new post at the Rcpp Galleryとして投稿した完全な解決策です - いくつかのコメントとサンプルの使用方法が含まれています。

// [[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); 
} 
+0

ありがとうございます。うまくいけば、私の完全なC++の無知は、私がまだ物事をコピーして貼り付けるのを妨げないでしょう。 – baptiste

+0

残念ながら、RcppDEにはあまりにも多くのことがあります。 'evaluate.h'では、新しいクラスが定義されていることが分かります。おそらく、任意のR関数を呼び出すかもしれません。親切な魂が余裕を持っていれば、素敵なhttp://gallery.rcpp.org/で最小限の例が得られます。 – baptiste

+0

ビネットを読み取ると、コードを見ている印象が確認されます。名前で選択されたコンパイルされた関数のみを処理したい場合は、この仮想クラスビジネスが必要ですか? – baptiste

関連する問題