40

次の 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 <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の提案に従って、例を適応させました。

4

1 に答える 1

32

svn log ...(時々 、ファイルの日付を確認するために on ファイルを使用する必要があります...)

C ベースの DEoptim を Rcpp / RcppArmadillo: RcppDE に「移植」すると、より良い使用例になると思います。その中で、最適化ルーチンが R 関数 (DEoptim のように) またはユーザー提供のコンパイル済み関数のいずれかを使用できるようにします。

C++ の足場が少しありますが、それに従うのに問題はないはずです。

2013-01-21 に編集以下は、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);
}
于 2013-01-20T20:10:36.170 に答える