c++rcppenvironmentr-packager-bigmemory

Loading a R package's function from Rcpp function in a new package namespace


I am developing a package for R and would like to load the functionalities of an R package inside an Rcpp function.

I know about Rcpp::Environment env("package:package_of_interest"), but this only works when the "package_of_interest" is loaded from R via library("package_of_interest"). Furthermore, I added the "package_of_interest" in the DESCRIPTION file below DEPENDS. That means, whenever I load my package with library("my_package") in R all functionalities are given as the desired package is auto-loaded. However, if I call the function via my_package::my_functionX(...) it drops an error and states that it can't convert the object to an environment: [type=character; target=ENVSXP]. enter image description here Is there any way to solve this problem? Can I convert the input (character) to target (ENVSXP)?

I previously studied Call a function from c++ via environment Rcpp and Rcpp trouble importing 'hessian' from R package 'numDeriv' and was confirmed with my approach.

In the following, I give you a minimal example to reproduce the error. With library(bigmemory) called first, this will work, but without not.

#include <iostream>
// [[Rcpp::depends(RcppArmadillo, BH, bigmemory)]]
#include <bigmemory/BigMatrix.h>
#include <bigmemory/MatrixAccessor.hpp>
#include <RcppArmadillo.h>
#include <Rdefines.h>
    
    
// [[Rcpp::export]]
void test_make_bm(std::size_t nrows, std::size_t ncols, std::string type, 
    bool separated = false, bool binarydescriptor = false, bool shared = true)
{

    // this line drops the error
    Rcpp::Environment bigmemory = Rcpp::Environment("package:bigmemory");
    // you can also directly call Rcpp::Environment bigmemory("package:bigmemory")
    
    Rcpp::Function big_matrix = bigmemory["big.matrix"];
            
    SEXP bm = big_matrix(
            Rcpp::_["nrow"] = nrows,
            Rcpp::_["ncol"] = ncols,
            Rcpp::_["type"] = type,
            Rcpp::_["init"] = R_NilValue,
            Rcpp::_["dimnames"] = R_NilValue,
            Rcpp::_["separated"] = separated,
            Rcpp::_["backingfile"] = R_NilValue,
            Rcpp::_["backingpath"] = R_NilValue,
            Rcpp::_["descriptorfile"] = R_NilValue,
            Rcpp::_["binarydescriptor"] = binarydescriptor,
            Rcpp::_["shared"] = shared);
        
    SEXP address = GET_SLOT(bm, Rf_install("address"));
    Rcpp::XPtr<BigMatrix> xptr(address);
        
    arma::mat m((double*) xptr->matrix(), xptr->nrow(), xptr->ncol());
    m.print();
    Rcpp::Rcout << "\n";
          
    return;

}

Is there any way to load the package from Rcpp? Does anyone know why bigmemory's BigMatrix has no constructor in C++?


Solution

  • So after some research, I present you the solution. In order to get access to the packagename::package_function() functionality you have to use the namespace_env function from the Environment namespace.

    #include <iostream>
    // [[Rcpp::depends(RcppArmadillo, BH, bigmemory)]]
    #include <bigmemory/BigMatrix.h>
    #include <bigmemory/MatrixAccessor.hpp>
    #include <RcppArmadillo.h>
    #include <Rdefines.h>
    
    // [[Rcpp::export]]
    void test_make_bm(std::size_t nrows, std::size_t ncols, std::string type, 
        bool separated = false, bool binarydescriptor = false, bool shared = true)
    {
    Rcpp::Environment bigmemory = Rcpp::Environment::namespace_env("bigmemory");
       Rcpp::Function big_matrix = bigmemory["big.matrix"];
                
       SEXP bm = big_matrix(
                Rcpp::_["nrow"] = nrows,
                Rcpp::_["ncol"] = ncols,
                Rcpp::_["type"] = type,
                Rcpp::_["init"] = R_NilValue,
                Rcpp::_["dimnames"] = R_NilValue,
                Rcpp::_["separated"] = separated,
                Rcpp::_["backingfile"] = R_NilValue,
                Rcpp::_["backingpath"] = R_NilValue,
                Rcpp::_["descriptorfile"] = R_NilValue,
                Rcpp::_["binarydescriptor"] = binarydescriptor,
                Rcpp::_["shared"] = shared);
            
        SEXP address = GET_SLOT(bm, Rf_install("address"));
        Rcpp::XPtr<BigMatrix> xptr(address);
            
        arma::mat m((double*) xptr->matrix(), xptr->nrow(), xptr->ncol());
        m.print();
        Rcpp::Rcout << "\n";
              
        return;   
    }