我正在尝试使用 Rcpp 制作一个包。我的所有C++功能都在一个.cpp文件中,如下所示:
double meanvec(NumericVector x) {
int n = x.size();
double tot = 0;
for (int i = 0; i < n; i++) {
tot += x[i];
}
tot /= n;
return tot;
}
double inprod(NumericVector u, NumericVector v) {
int m = u.size();
double val = 0;
for (int i = 0; i < m; i++) {
val += u[i] * v[i];
}
return val;
}
NumericVector lincoef(NumericVector x, NumericVector y) {
int n = x.size();
double xm = meanvec(x);
double ym = meanvec(y);
NumericVector xa(n);
for (int i = 0; i < n; i++) {
xa[i] = x[i] - xm;
}
NumericVector ya(n);
for (int i = 0; i < n; i++) {
ya[i] = y[i] - ym;
}
double b1 = inprod(xa, ya) / inprod(xa, xa);
double b0 = ym - (b1 * xm);
NumericVector beta = NumericVector::create(b0, b1);
return beta;
}
Run Code Online (Sandbox Code Playgroud)
基本上,最后一个函数将两个向量作为输入并输出一个向量。我想将此函数调用到一个单独的.R文件中,我试图在其中编写另一个函数。像这样的东西:
#' Title
#'
#' @param x Numeric vector.
#' @param y Numeric vector.
#'
#' @return
#' @export
linfit338 = function(x, y){
beta = .Call(`_pkg338_lincoef`, x, y)
fmod = function(x){
beta[1] + beta[2]*x
}
flist = list(beta, fmod)
return(flist)
}
Run Code Online (Sandbox Code Playgroud)
这里的输出是一个列表,其中第一个元素是来自C++被调用函数的向量,第二个元素是创建的函数。当我尝试安装并重新启动时,我收到此错误消息:
RcppExports.o:RcppExports.cpp:(.rdata+0x790): undefined reference to `_pkg338_lincoef'
Run Code Online (Sandbox Code Playgroud)
我的猜测是这与导出函数有关。当我在文件中// [[Rcpp::export]]的lincoef函数上方添加时C++,我没有收到任何错误消息,并且我的最终R函数有效。但是,我的整个目标是我根本不想lincoef导出该函数。
有任何解决这个问题的方法吗?我也愿意接受有关如何改进组织这些文件的建议,因为这是我第一次使用Rcpp.
All*_*ron 10
我认为您可能混淆了导出要在 R 中使用的 C++ 代码的概念(via // [[Rcpp::export]]),这与从包中导出 R 函数完全不同,即将这些函数提供给包的最终用户。
为了让您的功能RCPP R里面调用可言,你需要给// [[Rcpp::export]]他们。如果不这样做,则 R 包中将无法使用任何 C++ 代码。
听起来您想要做的是在包中使用 Rcpp 导出的函数,但对最终用户隐藏它们。这是 Rcpp 的一个常见用例,因为它允许您将 R 函数用作 C++ 代码的最终用户界面,同时让您可以在未来的开发中自由更改 C++ 实现,而不会破坏现有用户的风险' 代码。
您在包中创建的任何函数,无论是 R 函数还是 Rcpp 导出的函数,都必须主动从包中导出以供最终用户使用。这是一个与 不同的概念// [[Rcpp::export]],它是从包的 R 代码中访问 C++ 函数所必需的。
如果您NAMESPACE在项目根目录的文件中指定任何 R 函数,则只会从您的 R 包中导出它们。因此,要导出,myfunction()您需要export(myfunction)在 NAMESPACE 文件中包含一行。您使用的是 roxygen2,只要您@export在 roxygen 骨架中写入,它就会自动生成此行。使用 roxygen 的导出系统的替代方法是exportPattern在NAMESPACE文件中指定一个使用正则表达式仅导出名称与特定模式匹配的函数。
我通常的工作流程是通过编写我的 C++ 函数来为任何 Rcpp 导出的函数添加一个句点,如下所示:
// [[Rcpp::export(.MyCppFunction)]]
int BoringFunction() { return 0; }
Run Code Online (Sandbox Code Playgroud)
我现在可以像这样从 R 调用 C++ 函数:
MyRFunction <- function()
{
result <- .MyCppFunction()
return(result)
}
Run Code Online (Sandbox Code Playgroud)
我的NAMESPACE文件中的第一行如下所示:
exportPattern("^[[:alpha:]]+")
Run Code Online (Sandbox Code Playgroud)
这意味着我的包中以字母开头的任何 R 函数都将被导出。由于我Rcpp::export以句点开头的所有函数,我可以在 R 包内部使用它们,但它们不会导出给最终用户。
换句话说,包的最终用户可以调用,MyRFunction()但如果他们尝试调用,则会收到错误.MyCppFunction