I'm quite new to Rcpp. Sorry If I'm missing something obvious.
but when I try to use an igraph function in Rcpp I face the following obvious error on the left:
"Cannot initialize a Variable of type 'RCPP:Environment' (aka,'int') with an lvalue of type 'const char[15]'
Here is the code
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector insideOfCommEdgeIdsCpp(CharacterVector g, CharacterVector v) {
Environment igraph("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
}
A few small errors in your file:
declared as NumericVector but nothing is returned
Environment igraph not set up correctly.
A corrected version is below. And it it worth repeating this: Any R functions called from C++ are still R functions that run at the speed of R functions.
Corrected code
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
// [[Rcpp::export]]
void insideOfCommEdgeIdsCpp(CharacterVector g, CharacterVector v) {
Environment igraph = Environment("package:igraph");
Function game_er = igraph["erdos.renyi.game"];
Function get_adjacency = igraph["get.adjacency"];
}
Related
My code is the following
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace std;
using namespace Rcpp;
using namespace arma;
//RNGScope scope;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat hh(arma::mat Z, int n, int m){
if(Z.size()==0){
Z = arma::randu<mat>(n,m); # if matrix Z is null, then generate random numbers to fill in it
return Z;
}else{
return Z;
}
}
Error reported:
conflicting declaration of C function 'SEXPREC* sourceCpp_1_hh(SEXP, SEXP, SEXP)'
Do you have any idea about this question?
Thank you in advance!
Let's slow down and clean up, following other examples:
Never ever include both Rcpp.h and RcppArmadillo.h. It errors. And RcppArmadillo.h pulls in Rcpp.h for you, and at the right time. (This matters for the generated code.)
No need to mess with RNGScope unless you really know what your are doing.
I recommend against flattening namespaces.
For reasons discussed elsewhere at length, you probably want R's RNGs.
The code doesn't compile as posted: C++ uses // for comments, not #.
The code doesn't compile as posted: Armadillo uses different matrix creation.
The code doesn't run as intended as size() is not what you want there. We also do not let a 'zero element' matrix in---maybe a constraint on our end.
That said, once repaired, we now get correct behavior for a slightly changed spec:
Output
R> Rcpp::sourceCpp("~/git/stackoverflow/63984142/answer.cpp")
R> hh(2, 2)
[,1] [,2]
[1,] 0.359028 0.775823
[2,] 0.645632 0.563647
R>
Code
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat hh(int n, int m) {
arma::mat Z = arma::mat(n,m,arma::fill::randu);
return Z;
}
/*** R
hh(2, 2)
*/
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/
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 <yourself#somewhere.net>
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
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.
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
*/
I am considering calling a R function from c++ via environment, but I got an error, here is what I did
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector call(NumericVector x){
Environment env = Environment::global_env();
Function f = env["fivenum"];
NumericVector res = f(x);
return res;
}
Type call(x), this is what I got,
Error: cannot convert to function
I know I can do it right in another way,
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, Function f) {
NumericVector res = f(x);
return res;
}
and type
callFunction(x,fivenum)
But still wondering why first method failed.
fivenum function is not defined in the global environment but in the stats package enviroment, so you should get it from that:
...
Environment stats("package:stats");
Function f = stats["fivenum"];
...
In addition to #digEmAll's answer, I would like to mention a more general approach, which mimics R's packagename::packagefunctionX(...) approach.
The advantage is that you don't have to call library("dependend_library"), i.e., in this case, library(stats). That is useful when you call a function from your package, without previously calling library.
// [[Rcpp::export]]
Rcpp::NumericVector five_nums(Rcpp::NumericVector x){
Rcpp::Environment stats = Rcpp::Environment::namespace_env("stats");
Rcpp::Function f = stats["fivenum"];
return Rcpp::NumericVector(f(x));
}
/*** R
five_nums(stats::rnorm(25, 2, 3))
*/
I hope this isn't too obvious, as I've searched all day and can't find the answer.
Say I have the following R file:
library(Rcpp)
sourceCpp("cfile.cpp")
giveOutput(c(1,2,3))
And it compiles the following C++ file:
#include <Rcpp>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector plusTwo(NumericVector x){
NumericVector out = x + 2.0;
return out;
}
NumericVector giveOutput(NumericVector a){
NumericVector b = plusTwo(a);
return b;
}
No matter what I try, the Rcpp preprocessor makes plusTwo() available, and giveOutput() not at all. The documentation I've been able to find says that this is the point at which one should create a package, but after reading the package vignette it seems an order of magnitude more complicated than what I need.
Short of explicitly defining plusTwo() inside giveOutput(), what can I do?
You are expected to use the export attribute in front of every function you wanted exported. So by correcting your file to
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector plusTwo(NumericVector x){
NumericVector out = x + 2.0;
return out;
}
// [[Rcpp::export]]
NumericVector giveOutput(NumericVector a){
NumericVector b = plusTwo(a);
return b;
}
I get the desired behaviour:
R> sourceCpp("/tmp/patrick.cpp")
R> giveOutput(1:3)
[1] 3 4 5
R> plusTwo(1:3)
[1] 3 4 5
R>
Oh, and creating a package is as easy as calling Rcpp.package.skeleton() (but read its help page, particularly for the attributes argument). I know of at least one CRAN package that started how you started here and clearly went via Rcpp.package.skeleton()...