2
votes
SEXP callFunction1(List network, List words, Function testWordContinuity){
  SEXP res = testWordContinuity(network, words);
  return res;
}

for(int i=0; i<(n_epochs); i++){
  NumericVector outputMatchTracker = history["output.match.tracker"];
  outputMatchTracker[i] = callFunction1(network, words, testWordContinuity);
}

The testWordContinuity function in R calls another function in R that returns a single numeric variable

All I'm doing with res is replacing values in a vector using the for loop. The first line after the beginning of the for loop is assigning outputMatchTracker to a vector of zeros (history["output.match.tracker"]) so I can loop over the zeros.

The error: "Cannot convert 'SEXP' to 'Rcpp::traits::storage_type<14>::type {aka double}' in assignment" occurs on the last line in the for loop above.

Is there a way to convert res from SEXP to float or double?

I realize a similar question has been asked here: Rcpp cannot convert ‘SEXP {aka SEXPREC*}’ to ‘double’ in initialization but that question was solved by using an Rcpp sugar function instead of an R function to avoid converting SEXP into a double.

If there is not a way to convert from SEXP to float or double, is there a common way to get around this problem besides just coding the R function in Rcpp?

Happy to provide more information if necessary,

Thank you.

Edit:

Minimum Reproducible Example:

In Rcpp:

// [[Rcpp::export]]
SEXP callFunction(Function func){
  SEXP res = func();
  return(res);
}

// [[Rcpp::export]]
NumericVector func1(Function func){
  for(int i=0; i<10; i++){
    NumericVector vect(10);
    vect[i] = callFunction(func);
  }
  return(vect);
}

Upon sourcing this code the error specified above will appear.

2
Welcome to StackOverflow! There is a lot of verbiage in your question, but no minimal reproducible example and as such little we can say in response. Please edit to provide something minimal yet complete that triggers the error. - Dirk Eddelbuettel
Have you tried the as<> operator? @DirkEddelbuettel authored an article that is very thorough for these type of things. It can be found here. - Joseph Wood
Psst @JosephWood Dirk has authored many wonderful Rcpp articles; however, I wrote that one :) - coatless
@coatless, I feel like an idiot. That was super careless and unintentional. I'm in the Rcpp Galary on a daily basis and found that article very fast, copied the link, and didn't even bother to look at the author. I'm very sorry. I have huge respect for you and promote your work and websites often. - Joseph Wood
The as<> operator did the trick. I had tried that before, but apparently with the incorrect syntax. Thank you! - thposs

2 Answers

0
votes

I believe you are supposed to use the REAL macro, which returns a pointer to the start of a double array. See https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Attributes for an example.

0
votes

As an extension of Simon Byrne's answer - there are 2 ways to achieve this that I am aware of:

  1. Remember that scalars in R are actually always vectors with a length of 1. Therefore convert an R SEXP object to an RCPP NumericVector and use index (square bracket) notation to reference the first element:
double callFunction1(List network, List words, Function testWordContinuity){
  SEXP res = testWordContinuity(network, words);
  NumericVector dblVec(res)
  return dblVec[0];
}
  1. use the REAL macro and de-reference the pointer (to the first element). This may well be a micro-optimisation compared to approach 1 (untested), but the bottleneck will almost certainly be the testWordContinuity R function. There is also an asReal function in the <Rinternals.h> C library, but given the REAL macro is included in the <Rcpp.h> header file, it would seem to add unnecessary complexity to bother including <Rinternals.h>.
double callFunction1(List network, List words, Function testWordContinuity){
  SEXP res = testWordContinuity(network, words);
  return *REAL(res);
}