Reputation: 2230
I am running the latest R and Rcpp under MacOS Sonoma. I am attempting to add a new function call C++ code to a very old package (Hmisc), setting things up using Rcpp::compileAttributes(). The new R function's .Call() to the C++ binary object results in object not found. Here's what I have in place:
DESCRIPTION
: Imports: Rcpp and LinkingTo: RcppNAMESPACE
: export('pMedian') and useDynLib(Hmisc, .registration=TRUE, .fixes='F_')
src/init.c
: several references to the old Fortran routines, nothing about the new C++ routinesrc/RcppExports.cpp
: (RcppExports.o
also present), contents:// 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
: has all the recommended code including // [[Rcpp::export]]
, and the hlqest
function runs fine in an interactive session in which the .cpp
code is loaded using Rcpp::sourceCpp
. hlqest.o
is also there.R/RcppExports.R
: contains the following and the resulting R function runs fine interactively as mentioned abovehlqest <- function(x) {
.Call(`_Hmisc_hlqest`, x)
}
R/pMedian.r
which contains the following#' 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)
}
After building the binary Hmisc
package and loading the package I get the following error upon running pMedian(1:5)
: Error in pMedian(1:5) : object '_Hmisc_hlqest' not found
. Any help is appreciated.
Upvotes: 0
Views: 56
Reputation: 1265
The idea is to put // [[Rcpp::export]]
above your function hlquest
.
What RcppExports.cpp
and RcppExports.R
then do is to ensure you can an R-callable hlquest(x)
-- as that is easier / simpler than the expression you show above, namely
.Call(`_Hmisc_hlqest`, x)
One or two more other things to pay attention to is that the NAMESPACE
has a line
useDynLib("Hmisc", .registration=TRUE)
as the .Call
above does not pass a string and does not reference the package. (And you show you have that, which is something I missed on my first read.)
I have also found that adding to an existing package is hardest in the sense that for a 'new' package without an src/init.c
the corresponding entries are automatically created in RcppExports.cpp
but if I remember correct the compileAttributes()
call is careful and will not modify an existing init.c
. So it is finicky -- but one you dot all i-s and cross all t-s it should work.
And as you write
src/init.c
: several references to the old Fortran routines, nothing about the new C++ routine
it might be best to check with a throw-away one-function package you can create what would be needed and to then add that manually to your existing src/init.c
.
Upvotes: 1