Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: pointer to c function

Tags:

c++

pointers

r

rcpp

How to pass a pointer to a function from C code to R (using External R) and after call that function from R??

Something like:

C:

typedef void (* FunctionPtr)();
SEXP ans;
PROTECT(ans = /* ?some code? */);
R_tryEval(ans, R_GlobalEnv, NULL);
UNPROTECT(1);

R:

callback_function()

EDIT: @Romain Francois's post was very helpful.
myapp code:

namespace
{
    void callback()
    {
        std::cout << "callback\n" << std::flush;
    }
}
class Worker
{
public:
/*...*/
    void initialize(argc, argv)
    {
       Rf_initEmbeddedR(argc, argv);

        SEXP ans, val;
        typedef void (* FunctionPtr)();

        PROTECT(ans = Rf_lang2(Rf_install("source"), Rf_mkString("script.R")));
        R_tryEval(ans, R_GlobalEnv, NULL);
        UNPROTECT(1);

        PROTECT(val = Rf_ScalarInteger((int)(&callback)));
        /* pass the address of the pointer to a function */
        PROTECT(ans = Rf_lang2(Rf_install("setCallback"), val));
        R_tryEval(ans, R_GlobalEnv, NULL);
        UNPROTECT(2);
    }
    void uninitialize()
    {
        Rf_endEmbeddedR(0);
    }
};

R and Rcpp
script.R

###################
sourceCpp("utils.cpp")
###################
callback <- function()
{
  callCallback()
}

utils.cpp

#include <Rcpp.h>

using namespace Rcpp;

typedef void (* Callback)();
static Callback spCallback = 0;

// [[Rcpp::export]]
void callCallback()
{
  if (spCallback) {
    spCallback();
  } else {
    Rprintf("ERROR: callback is not set");
  }
}
// [[Rcpp::export]]
void setCallback(const int address)
{
  spPlaceOrder = (Callback)address;
}
like image 577
Andrii Avatar asked Dec 26 '22 12:12

Andrii


1 Answers

Another way is to use the InternalFunction class in Rcpp:

#include <Rcpp.h>
using namespace Rcpp ;

void callback(){
    Rprintf( "hello from calback\n" ) ;    
}

// [[Rcpp::export]]
InternalFunction get_callback(){
    return InternalFunction(callback) ;    
}

The implementation is similar to what I described in the other answer. Things on the R side are taken care of by Rcpp:

callback <- get_callback()
callback()
like image 161
Romain Francois Avatar answered Dec 29 '22 02:12

Romain Francois