[英]Loading a R package's function from Rcpp function in a new package namespace
我正在為 R 開發 package,並希望在 Rcpp function 中加載 R package 的功能。
我知道 Rcpp::Environment env("package:package_of_interest"),但這僅在通過庫("package_of_interest")從 R 加載“package_of_interest”時有效。 此外,我在 DEPENDS 下面的 DESCRIPTION 文件中添加了“package_of_interest”。 這意味着,每當我在 R 中使用庫(“my_package”)加載我的 package 時,所有功能都會自動加載,因為所需的 package 會自動加載。 但是,如果我通過 my_package::my_functionX(...) 調用 function,它會拋出一個錯誤並聲明它無法將 object 轉換為環境:[type=character; 目標 = ENVSXP]。 有什么辦法可以解決這個問題嗎? 我可以將輸入(字符)轉換為目標(ENVSXP)嗎?
我之前通過環境 Rcpp 研究了從 c++ 調用 function和Rcpp trouble importing 'hessian' from R package 'numDeriv'並通過我的方法得到了確認。
在下文中,我給你一個最小的例子來重現錯誤。 首先調用 library(bigmemory) ,這將起作用,但沒有。
#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;
}
有沒有辦法從 Rcpp 加載 package? 有誰知道為什么bigmemory的BigMatrix在C++沒有構造函數?
這與其中一個單元測試文件基本相同,只要它存在,就已經記錄了這種行為。 如果您需要尚未附加的 package 中的 function,則需要通過命名空間連接到 go。
> Rcpp::cppFunction(paste0("double mysd(NumericVector x) { ",
r"(Environment ns = Environment::namespace_env("stats");)",
r"(Function f = ns["sd"]; return as<double>(f(x)); })"))
> mysd(1:10)
[1] 3.02765
> mysd(1:10)
[1] 3.02765
>
(為了可讀性,我將cppFunction()
調用分為三行,但你可以只寫一行,這也是我編寫它來測試它的方式。)
因此,經過一番研究,我向您介紹了解決方案。 為了訪問 packagename::package_function() 功能,您必須使用 Environment 命名空間中的 namespace_env function。
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.