Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing user created c++ functions in rcpp as arguments

Tags:

r

rcpp

This might be a basic question, I have been struggling with passing user created c++ functions in Rcpp. I read the documentation and it seems that I should use the SEXP wrapping offered by XPtr (Link:http://gallery.rcpp.org/articles/passing-cpp-function-pointers/ ) However, it is still not quite clear to me how to do this properly. In what follows, I want to use a function as funcPtrG as an argument in testfun, the C++ way. I get the error as below:

     #include <RcppArmadillo.h>
        typedef double (*funcPtrG)(double theta, double gamma);
        using namespace Rcpp;

    // [[Rcpp::export]]
    double GGfuncpp(double theta, double gamma){
      double new_gamma = 0;
      new_gamma = theta*gamma + R::rnorm(0,1)*0.0001;
      return new_gamma;
    }
    // [[Rcpp::export]]
    double testfun(funcPtrG fun2, double theta, double gamma){
      double x= 0;
      x = fun2(theta,gamma);
      return x;
    }

    Error: cannot convert 'SEXP' to 'double (*)(double, double)' in initialization

I attempted putting x = XPtr<funcPtr>fun2(theta,gamma) but didn't give a desired result.

like image 364
dleal Avatar asked Feb 05 '23 14:02

dleal


1 Answers

IIUC, you are looking for something like this:

#include <Rcpp.h>
using namespace Rcpp;

typedef double (*funcPtrG)(double theta, double gamma);
typedef XPtr<funcPtrG> fptr_t;

// [[Rcpp::export]]
double GGfuncpp(double theta, double gamma)
{
    Rcout << "GGfuncpp called\n";
    double new_gamma = 0;
    new_gamma = theta*gamma + R::rnorm(0, 1) * 0.0001;
    return new_gamma;
}

// [[Rcpp::export]]
double GGfuncpp2(double theta, double gamma)
{
    Rcout << "GGfuncpp2 called\n";
    return 1.0;
}

// [[Rcpp::export]]
fptr_t make_GGfuncpp()
{
    return fptr_t(new funcPtrG(GGfuncpp));
}

// [[Rcpp::export]]
fptr_t make_GGfuncpp2()
{
    return fptr_t(new funcPtrG(GGfuncpp2));
}

// [[Rcpp::export]]
double testfun(fptr_t fun2, double theta, double gamma)
{
    double x= 0;
    x = (*fun2)(theta, gamma);
    return x;
}

/*** R

fptr1 <- make_GGfuncpp()
fptr2 <- make_GGfuncpp2()

testfun(fptr1, 1, 5)
# GGfuncpp called
# [1] 5.000084

testfun(fptr2, 1, 5)
# GGfuncpp2 called
# [1] 1

*/

R does not have any concept of a funcPtrG, so you cannot pass it directly as a function parameter type. Instead, these objects need to be wrapped in the XPtr template. The make_GGfuncpp and make_GGfuncpp2 functions provide a means of creating XPtr<funcPtrG> instances on the R side, which can then be passed back to C++ via function argument.

like image 87
nrussell Avatar answered Feb 07 '23 08:02

nrussell