Reputation: 179
I am trying to build a package that uses the function 'hessian' from the package 'numDeriv'. However, when I build the package and run the code I get the error
Cannot convert object to an environment: [type=character; target=ENVSXP].
Example simplified Rcpp code below
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <stdio.h>
#include<armadillo>
using namespace Rcpp;
using namespace std;
double testfunc(double X){
return pow(X+1,2);
}
double hessian_rcpp(double X){
Rcpp::Environment numDeriv("package:numDeriv");
Rcpp::Function hessian = numDeriv["hessian"];
Rcpp::List hessian_results = hessian(
Rcpp::_["func"] = Rcpp::InternalFunction(testfunc),
Rcpp::_["x"] = X);
arma::vec out = Rcpp::as<arma::vec>(hessian_results[0]);
return out[0];
}
// [[Rcpp::export]]
double returnhess(double X){
double out = hessian_rcpp(X);
return out;
}
Then after building the package running the following R code results in the error.
library(test)
returnhess(X=3)
Error in returnhess(X = 3) :
Cannot convert object to an environment: [type=character; target=ENVSXP].
My NAMESPACE is
useDynLib(test, .registration=TRUE)
importFrom(Rcpp, evalCpp)
exportPattern("^[[:alpha:]]+")
My DESCRIPTION is
Package: test
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Author: Who wrote it
Maintainer: The package maintainer <[email protected]>
Description: More about what it does (maybe more than one line) Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
Imports: Rcpp, RcppArmadillo, numDeriv
LinkingTo: Rcpp, RcppArmadillo, numDeriv
Encoding: UTF-8
LazyData: true
My R version is 3.5.1, RStudio version is 1.1.456, Rcpp version is 0.12.19, RcppArmadillo version is 0.9.100.5.0, numDeriv version is 2016.8.1. My operating system is windows 10.
I was able to successfully import 'optimize' from the R package 'stats' with an analogous approach. Example simplified code below
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <stdio.h>
#include<armadillo>
using namespace Rcpp;
using namespace std;
double testfunc(double X){
return pow(X+1,2);
}
double optim_rcpp(){
Rcpp::Environment stats("package:stats");
Rcpp::Function optimize = stats["optimize"];
Rcpp::List opt_results = optimize(
Rcpp::_["f"] = Rcpp::InternalFunction(testfunc),
Rcpp::_["lower"] = -10,
Rcpp::_["upper"] = 10);
arma::vec out = Rcpp::as<arma::vec>(opt_results[0]);
return out[0];
}
// [[Rcpp::export]]
double returnoptim(){
double out = optim_rcpp();
return out;
}
Same NAMESPACE and DESCRIPTION as above
Then running the following R code works
returnoptim()
[1] -1
Upvotes: 3
Views: 719
Reputation: 119
In addition to @RalfStubner's answer, I would like to point out the following. The Rcpp::Environment namespace has a function namespace_env("the_package_name"). This gives you the same functionality as in R's approach packagename::package_functionX(...). In combination with Depends or Imports in your DESCRIPTION file, you are on the safe side. Based on it you can proceed as follows:
#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
double testfunc(double X){
return std::pow(X+1,2);
}
double optim_rcpp(){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function optimize = stats["optimize"];
Rcpp::List opt_results = optimize(
Rcpp::_["f"] = Rcpp::InternalFunction(testfunc),
Rcpp::_["lower"] = -10,
Rcpp::_["upper"] = 10);
arma::vec out = Rcpp::as<arma::vec>(opt_results[0]);
return out[0];
}
// [[Rcpp::export]]
double returnoptim(){
return optim_rcpp();
}
/*** R
returnoptim() # -1
*/
And to answer @mike's question directly, you can also do so:
#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
double testfunc(double X){
return std::pow(X+1,2);
}
double hessian_rcpp(double X){
Rcpp::Environment numDeriv = Rcpp::Environment::namespace_env("numDeriv");
Rcpp::Function hessian = numDeriv["hessian"];
Rcpp::List hessian_results = hessian(
Rcpp::_["func"] = Rcpp::InternalFunction(testfunc),
Rcpp::_["x"] = X);
arma::vec out = Rcpp::as<arma::vec>(hessian_results[0]);
return out[0];
}
// [[Rcpp::export]]
double returnhess(double X){
return hessian_rcpp(X);
}
/*** R
returnhess(X=3) # 2
*/
Upvotes: 0
Reputation: 26833
As a workaround you can add
Depends:numDeriv
to your DESCRIPTION
. This ensures that the numDeriv
package is loaded together with your package.
BTW: I would refrain from using using namespace Rcpp;
in a package. And I would never use using namespace std;
. I cannot think of a good reason to use #include <stdio.h>
and #include<armadillo>
is unnecessary when RcppArmadillo
is used.
Upvotes: 4