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

Serguei Sokol serguei.sokol at gmail.com
Mon Mar 6 10:11:26 CET 2017


Le 04/03/2017 à 20:41, Nathan Russell a écrit :
> 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)
I came across the same issue with the package rmumps and applied a simplified workaround:
- created an empty init.c (my package has only module export and no
C-callable functions, so tools::package_native_routine_registration_skeleton()
did not help)
8<-------- src/init.c
#include <R.h>
#include <Rinternals.h>
#include <stdlib.h> // for NULL
#include <R_ext/Rdynload.h>

void R_init_rmumps(DllInfo *dll)
{
     R_registerRoutines(dll, NULL, NULL, NULL, NULL);
     R_useDynamicSymbols(dll, TRUE);
}

8<-------- end of init.c
- in NAMESPACE I have put (note .registration=TRUE):
useDynLib(rmumps, .registration=TRUE)
exportPattern("^[[:alpha:]]+")
import(methods, Rcpp)
# plus some S3 methods I have defined

For now, it keeps silent the check routine of R-devel.

Serguei.

>
> - 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.old2017-03-04 12:40:07.639280221 -0500
> # --- mod/src/init.c2017-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)
>
>
>
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>



More information about the Rcpp-devel mailing list