Reputation: 23
I'm new for Rcpp, and in my code, I must call the R function "optim" from C++. I referred to many examples, but there is still a mistake: "static assertion failed: cannot convert type to SEXP". Here is my code, and the problem is the last function:
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace RcppArmadillo;
using namespace arma;
using namespace std;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
double fr(arma::colvec x){
double result = 100 * (x(2) - x(1) * x(1)) * (x(2) - x(1) * x(1)) + (1 - x(1)) * (1 - x(1));
return result;
}
typedef double (*funcPtr)(arma::colvec x);
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr(){
return(XPtr<funcPtr>(new funcPtr(&fr)));
}
// [[Rcpp::export]]
arma::colvec callOptimFun(SEXP x) {
RNGScope scope;
Rcpp::Environment stats("package:stats");
Rcpp::Function optim = stats["optim"];
XPtr<funcPtr> xpfun = putFunPtrInXPtr();
funcPtr fun = *xpfun;
Rcpp::List y = optim(x, fun);
arma::colvec r = y["par"];
return r;
}
Unfortunately, I have tried lots of methods for my last function, and all methods have the same error. These are my tries: 1.
// [[Rcpp::export]]
Rcpp::List callOptimFun(arma::colvec x) {
\\....
Rcpp::List y = optim(x, fun);
return y;
}
2.
// [[Rcpp::export]]
Rcpp::List callOptimFun(arma::colvec x) {
\\....
Rcpp::List y = optim(x, fun);
return y;
}
3.
// [[Rcpp::export]]
Rcpp::List callOptimFun(SEXP x) {
\\....
Rcpp::List y = optim(x, fun);
return y;
}
I am not familiar with C++. What may be the problem? Thanks!
Upvotes: 2
Views: 1079
Reputation: 20746
In this case, the use of a functional pointer is problematic. Rcpp has a special type of wrapper that requires the C++ function to not be exported into R called Rcpp::InternalFunction
. Under this implementation, you're able to easily incorporate R's optim
with your C++ function from C++!
Also, I modified the element accessed indexes in fr
function. The reason for this modification is you are hitting an out-of-bounds error because the indexes in C++ are on a zero-based starting system not a one-based system starting system like R. (e.g. x(0)
is the same as x[1]
in R)
#include<RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
double fr(arma::vec x){
double result = 100 * (x(1) - x(0) * x(0)) * (x(1) - x(0) * x(0)) + (1 - x(0)) * (1 - x(0));
return result;
}
// [[Rcpp::export]]
arma::vec optim_rcpp(const arma::vec& init_val){
Rcpp::Environment stats("package:stats");
Rcpp::Function optim = stats["optim"];
Rcpp::List opt_results = optim(Rcpp::_["par"] = init_val,
Rcpp::_["fn"] = Rcpp::InternalFunction(&fr),
Rcpp::_["method"] = "BFGS");
// Extract and coerce from list.
arma::vec out = Rcpp::as<arma::vec>(opt_results[0]);
return out;
}
Upvotes: 4