[Rcpp-devel] Symbol registration in packages with module classes

Nathan Russell russell.nr2012 at gmail.com
Sat Mar 4 20:41:12 CET 2017


To summarize an issue I recently encountered,

- Beginning in R 3.4, R CMD check will (likely) expect users to register
symbols for native routines (see e.g. this discussion:
https://github.com/RcppCore/Rcpp/issues/636)

- Generally speaking, the
function tools::package_native_routine_registration_skeleton seems to
generate the appropriate boilerplate code, which can then be placed in
src/init.c to appease R CMD check

- However, packages using Rcpp modules will contain extra symbols of the
form '_rcpp_module_boot_modulename' (resulting from a call to
Rcpp::loadModule("modulename") AFAICT), which do __not__ get picked up by
package_native_routine_registration_skeleton

- Such packages will build correctly, but throw an error when you attempt
to load them:

"Unable to load module "modulename": Failed to initialize module pointer:
Error in FUN(X[[i]], ...):
    no such symbol _rcpp_module_boot_modulename in package whatever"

- To fix this, one can manually add corresponding entries to the code
generated by package_native_routine_registration_skeleton, i.e. a
declaration

extern SEXP _rcpp_module_boot_modulename(void);

and an entry in the CallEntries array

{"_rcpp_module_boot_modulename", (DL_FUNC) &_rcpp_module_boot_modulename, 0}

----------

If nothing else, I'm just putting this information out in the open for
others who run into this issue. However, if anyone has thoughts on
addressing this, either from the Rcpp side, or by making changes to
tools::package_native_routine_registration_skeleton, or something else,
please chime in.


Nate

----------

Steps to reproduce from a terminal, using the stock Rcpp modules:


cd /tmp
Rscript -e 'Rcpp::Rcpp.package.skeleton("mod", path = "/tmp", module =
TRUE); Rcpp::compileAttributes("mod")'
R CMD build mod && R CMD check --as-cran mod_1.0.tar.gz
# as expected:
# * checking compiled code ... NOTE
# File ‘mod/libs/mod.so’:
#   Found no calls to: ‘R_registerRoutines’, ‘R_useDynamicSymbols’
#
# It is good practice to register native routines and to disable symbol
# search.

Rscript -e 'tools::package_native_routine_registration_skeleton("mod")' |
tee mod/src/init.c
# #include <R.h>
# #include <Rinternals.h>
# #include <stdlib.h> // for NULL
# #include <R_ext/Rdynload.h>
#
# /* FIXME:
#    Check these declarations against the C/Fortran source code.
# */
#
# /* .Call calls */
# extern SEXP mod_rcpp_hello_world();
#
# static const R_CallMethodDef CallEntries[] = {
#     {"mod_rcpp_hello_world", (DL_FUNC) &mod_rcpp_hello_world, 0},
#     {NULL, NULL, 0}
# };
#
# void R_init_mod(DllInfo *dll)
# {
#     R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
#     R_useDynamicSymbols(dll, FALSE);
# }

R CMD build mod && R CMD check --as-cran mod_1.0.tar.gz
# ...
# * checking whether package ‘mod’ can be installed ... ERROR
# Installation failed.
# See ‘/tmp/mod.Rcheck/00install.out’ for details.
# ...

tail mod.Rcheck/00install.out
# *** installing help indices
# ** building package indices
# ** testing if installed package can be loaded
# Error: package or namespace load failed for ‘mod’ in
.doLoadActions(where, attach):
#  error in load action .__A__.1 for package mod: loadModule(module =
"NumEx", what = TRUE, env = ns, loadNow = TRUE):
#    Unable to load module "NumEx": Failed to initialize module pointer:
Error in FUN(X[[i]], ...):
#    no such symbol _rcpp_module_boot_NumEx in package mod
#    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Error: loading failed
# Execution halted
# ERROR: loading failed
# * removing ‘/tmp/mod.Rcheck/mod’

grep '^loadModule' mod/R/zzz.R
# loadModule("NumEx", TRUE)
# loadModule("yada", TRUE)
# loadModule("stdVector", TRUE)

# changes
diff -c init.c.old mod/src/init.c
# *** init.c.old 2017-03-04 12:40:07.639280221 -0500
# --- mod/src/init.c 2017-03-04 12:54:50.295290658 -0500
# ***************
# *** 9,17 ****
# --- 9,23 ----
#
#   /* .Call calls */
#   extern SEXP mod_rcpp_hello_world();
# + extern SEXP _rcpp_module_boot_NumEx(void);
# + extern SEXP _rcpp_module_boot_yada(void);
# + extern SEXP _rcpp_module_boot_stdVector(void);
#
#   static const R_CallMethodDef CallEntries[] = {
#       {"mod_rcpp_hello_world", (DL_FUNC) &mod_rcpp_hello_world, 0},
# +     {"_rcpp_module_boot_NumEx", (DL_FUNC) &_rcpp_module_boot_NumEx, 0},
# +     {"_rcpp_module_boot_yada", (DL_FUNC) &_rcpp_module_boot_yada, 0},
# +     {"_rcpp_module_boot_stdVector", (DL_FUNC)
&_rcpp_module_boot_stdVector, 0},
#       {NULL, NULL, 0}
#   };

R CMD build mod && R CMD check --as-cran mod_1.0.tar.gz
# success
# ...
# * checking PDF version of manual ... OK
# * DONE
#
# Status: 1 NOTE
#         ^^^^^^ (unrelated)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20170304/a564d736/attachment.html>


More information about the Rcpp-devel mailing list