我正在 MacOS Sonoma 下运行最新的 R 和 Rcpp。 我正在尝试将新的函数调用 C++ 代码添加到一个非常旧的包 (Hmisc) 中,并使用 Rcpp::compileAttributes() 进行设置。 新的 R 函数对 C++ 二进制对象的 .Call() 会导致找不到对象。 这是我所拥有的:
DESCRIPTION
:导入:Rcpp 和 LinkingTo:RcppNAMESPACE
:导出('pMedian')和useDynLib(Hmisc,.registration = TRUE,.fixes ='F_')
src/init.c
:对旧 Fortran 例程的多次引用,与新 C++ 例程无关src/RcppExports.cpp
:(RcppExports.o
也存在),内容:// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#include <Rcpp.h>
using namespace Rcpp;
#ifdef RCPP_USE_GLOBAL_ROSTREAM
Rcpp::Rostream<true>& Rcpp::Rcout = Rcpp::Rcpp_cout_get();
Rcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();
#endif
// hlqest
double hlqest(NumericVector x);
RcppExport SEXP _Hmisc_hlqest(SEXP xSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP);
rcpp_result_gen = Rcpp::wrap(hlqest(x));
return rcpp_result_gen;
END_RCPP
}
src/hlqest.cpp
:拥有包括 // [[Rcpp::export]]
在内的所有推荐代码,并且 hlqest
函数在交互式会话中运行良好,其中使用 .cpp
加载 Rcpp::sourceCpp
代码。 hlqest.o
也在那里。R/RcppExports.R
:包含以下内容,并且生成的 R 函数可以交互地运行良好,如上所述hlqest <- function(x) {
.Call(`_Hmisc_hlqest`, x)
}
R/pMedian.r
其中包含以下内容#' Pseudomedian
#'
#' Uses fast C++ code from the `DescTools` package to compute the pseudomedian of a numeric vector. The pseudomedian is the median of all possible midpoints of two different observations. The C++ code is originally from Monahan and Moser. The pseudomedian is also called the Hodges-Lehmann one-sample estimator.
#' @title pMedian
#' @param x a numeric vector
#' @param na.rm set to `TRUE` to exclude `NA`s before computing the pseudomedian
#'
#' @return a scalar numeric value
#' @export
#' @md
#' @seealso <https://dl.acm.org/doi/10.1145/1271.319414>, <https://www4.stat.ncsu.edu/~monahan/jul10>
#' @examples
#' x <- 1:5
#' pMedian(x)
#' # Compare with brute force calculation and with wilcox.test
#' median(outer(x, x, '+')) / 2
#' wilcox.test(x, conf.int=TRUE)
pMedian <- function(x, na.rm = FALSE) {
if(na.rm) x <- x[! is.na(x)]
n <- length(x)
if(n == 0) return(NA_real_)
if(n == 1) return(as.double(x))
.Call(`_Hmisc_hlqest`, x)
}
构建二进制
Hmisc
包并加载该包后,我在运行 pMedian(1:5)
时收到以下错误:Error in pMedian(1:5) : object '_Hmisc_hlqest' not found
。 如有任何帮助,我们将不胜感激。
这个想法是将
// [[Rcpp::export]]
放在你的函数 hlquest
之上。
RcppExports.cpp
和 RcppExports.R
然后做的是确保您可以进行 R 可调用 hlquest(x)
—— 因为这比上面显示的表达式更容易/更简单,即
.Call(`_Hmisc_hlqest`, x)
还有一两点需要注意的是
NAMESPACE
有一条线
useDynLib("Hmisc", .registration=TRUE)
因为上面的
.Call
不传递字符串并且不引用包。
我还发现,添加到现有包是最难的,因为对于没有
src/init.c
的“新”包,相应的条目会在 RcppExports.cpp
中自动创建,但如果我记得正确,compileAttributes()
调用就会小心并且不会修改现有的init.c
。 所以它很挑剔——但是如果你点了所有的 i-s 并交叉了所有的 t-s,它应该可以工作。