如何用RcppArmadillo构建R包?遇.Call()错误求助
在Ubuntu系统下使用R语言,借助roxygen2和devtools构建包含RcppArmadillo代码的R包时,执行包检查出现以下错误:
Error in .Call("_pqfe_loss_qr", PACKAGE = "pqfe", beta, x, y, tau, N, :
"_pqfe_loss_qr" not available for .Call() for package "pqfe"
Calls: qr ... optim_qr ->-> -> fn -> .Call
Execution halted
同时伴随警告:
Warning message:
Can't find genericsewin package knitr to register S3 method.
This message is only shown to developers using devtools.
Do you need to update knitr to the latest version?
相关配置与代码信息:
- DESCRIPTION依赖配置:
Depends: R (>= 3.4.4), MASS (>= 7.3-49), Rcpp (>= 1.0.5), RcppArmadillo (>= 0.9.900.2.0)
LinkingTo: Rcpp, RcppArmadillo
- /src目录下的
loss_function.cpp代码:
// [[Rcpp::depends(RcppArmadillo)]] #include <RcppArmadillo.h> using namespace Rcpp; //' Check function. //' //' @param x vector //' @param tau percentile //' @return y new vector // [[Rcpp::export(rho_koenker)]] arma::vec rho_koenker(arma::vec x, double tau){ int n = x.n_elem; arma::vec y(n); for(int i = 0; i < n; ++i){ if(x(i)<0){ y(i) = x(i)*(tau-1); } else { y(i) = x(i)*tau; } } return(y); } //' Quantile regression loss function //' //' @param beta parameter //' @param x matrix //' @param y vector //' @param tau percentile //' @param N total number of observations //' @param d beta's length //' @return eta numeric // [[Rcpp::export(loss_qr)]] double loss_qr(arma::vec beta, arma::mat x, arma::vec y, double tau, int N, int d){ double eta = 0; arma::vec res(N); arma::vec rho(N); res = y - (x * beta); rho = rho_koenker(res,tau); eta = accu(rho); return(eta); }
1. 核心错误:.Call找不到函数的处理
该错误说明C++函数未被正确编译链接到包中,或导出信息未生成,按以下步骤修复:
- 执行完整构建流程:先运行
devtools::document()生成NAMESPACE和Rd文档,再运行devtools::build()编译C++代码,最后执行devtools::check()。roxygen2需要处理// [[Rcpp::export]]标签生成NAMESPACE导出条目,不可跳过document步骤。 - 检查NAMESPACE文件:确认包含以下条目,若缺失则重新运行
devtools::document()自动生成:useDynLib(pqfe, .registration = TRUE) export(rho_koenker) export(loss_qr) - 清理旧编译产物:删除包目录下的
src/*.o、src/*.so、R/RcppExports.R文件,再重新执行devtools::document()和devtools::build(),确保编译从头开始。
2. knitr警告的处理
该警告是devtools与旧版本knitr的兼容性问题,直接升级knitr即可消除:
install.packages("knitr")
3. 额外优化建议
- 移除冗余配置:删除C++代码中的
// [[Rcpp::depends(RcppArmadillo)]]标签,DESCRIPTION的LinkingTo已声明依赖,包环境中无需重复配置。 - 简化函数参数:
loss_qr中的N和d可通过y.n_elem和beta.n_elem直接获取,无需作为参数传入,修改后代码如下:
// [[Rcpp::export(loss_qr)]] double loss_qr(arma::vec beta, arma::mat x, arma::vec y, double tau){ arma::vec res = y - x * beta; arma::vec rho = rho_koenker(res, tau); return accu(rho); }
内容的提问来源于stack exchange,提问作者Ian Niewicz

