简体   繁体   中英

Call Rcpp c++ function from R code in the same package

I want to build an Rcpp package with C++ and R code. With the C++ code only (R code removed), everything compiles and works nicely and after building and loading the exported functions are callable as expected as

<packageName>::<functionName>()

However, when including the R code with the call to the C++ code, I get an object not found error when building the package:

R CMD build <packageName>
[...]
** R
** byte-compile and prepare package for lazy loading
Error in <functionName>() :
  object '_<packageName>_<functionName>' not found
Error: unable to load R code in package '<packageName>'

The error happens after the C++ code is successfully compiled.

<functionName>()

is mapped to

_<packageName>_<functionName>

in R/RcppExports.R as usual, but it does not appear that it can be loaded by the R code at build time.

The structure of the package is as usual:

<packageName>
├── DESCRIPTION
├── man
│   ├── <functionName>.rd
│   └── <packageName>-package.rd
├── NAMESPACE
├── R
│   ├── <RCodeFileName>.R
│   └── RcppExports.R   
├── README.md
└── src
    ├── <C++CodeFileName>.cpp
    ├── <C++CodeFileName>.o
    ├── <packageName>.so
    ├── RCppExports.cpp
    ├── RCppExports.o
    └── symbols.rds

where the .o and .so files are produced when compiling the package.

The R file calls the function from the C++ file directly:

[other stuff]
[...]
<functionName>()

NAMESPACE file is also as usual:

useDynLib(<packageName>, .registration=TRUE)
importFrom(Rcpp, evalCpp)
exportPattern("^[[:alpha:]]+")

This seems like a very simple and straight forward problem (calling C++ code from R code in an Rcpp package). Nevertheless, I seem to be unable to find any indication of how this should be done.

Edit (Apr 8 2020): build vs. INSTALL

The problem will occur in every case for

R CMD INSTALL <packageName>_<version>.tar.gz

If the included help file

man/<packageName>-package.Rd

is built so that it forces installing the package to process help pages the error will already occur in

R CMD build <packageName>

as described above.

Edit (Apr 8 2020): Steps to reproduce with Rcpp.package.skeleton() (on Unix-like systems anyway)

Rscript -e 'Rcpp::Rcpp.package.skeleton("demo20200408")'
echo 'rcpp_hello_world()' > errorDemo/R/example.R
R CMD INSTALL errorDemo

You may want to slow dowm. The Rcpp package itself comes with a demo package generator via the Rcpp.package.skeleton() function. Run it!

The compare piece by piece to what you have.

A second generator is e.g.built into RStudio and available under the File -> New Project -> New directory -> Package with Rcpp menu options.

Otherwise, hard to tell. Did you do anything funky to you function name? Because these are mapped to R and C++ you have restrictions from both. Ie you cannot use a dot (as that would be a class method notation in C++).

Lastly, even when unexported the C++ function should be available from the installed and loaded package via three colons, ie mypkg:::myFun() .

Lastly, quick demo:

Create it
edd@rob:/tmp$ Rscript -e 'Rcpp::Rcpp.package.skeleton("demo20200408")' Creating directories... Creating DESCRIPTION... Creating NAMESPACE... Creating Read-and-delete-me... Saving functions and data... Making help files... Done. Further steps are described in './demo20200408/Read-and-delete-me'. Adding Rcpp settings >> added Imports: Rcpp >> added LinkingTo: Rcpp >> added useDynLib directive to NAMESPACE >> added importFrom(Rcpp, evalCpp) directive to NAMESPACE >> added example src file using Rcpp attributes >> added Rd file for rcpp_hello_world >> compiled Rcpp attributes edd@rob:/tmp$
Install it
edd@rob:/tmp$ Rscript -e 'library(demo20200408); rcpp_hello_world()'
[[1]]
[1] "foo" "bar"

[[2]]
[1] 0 1

edd@rob:/tmp$ 
Run it
edd@rob:/tmp$ Rscript -e 'library(demo20200408); rcpp_hello_world()' [[1]] [1] "foo" "bar" [[2]] [1] 0 1 edd@rob:/tmp$
And add an R function and call it too
edd@rob:/tmp$ echo 'r_hello_world <- function() cat("hi there\n")' > demo20200408/R/foo.R edd@rob:/tmp$ R CMD INSTALL demo20200408 * installing to library '/usr/local/lib/R/site-library' * installing *source* package 'demo20200408'... ** using staged installation ** libs make: Nothing to be done for 'all'. installing to /usr/local/lib/R/site-library/00LOCK-demo20200408/00new/demo20200408/libs ** R ** byte-compile and prepare package for lazy loading ** help *** installing help indices ** building package indices ** testing if installed package can be loaded from temporary location ** checking absolute paths in shared objects and dynamic libraries ** testing if installed package can be loaded from final location ** testing if installed package keeps a record of temporary installation path * DONE (demo20200408) edd@rob:/tmp$ Rscript -e 'library(demo20200408); r_hello_world()' hi there edd@rob:/tmp$
Still no issue despite OP's claims

In the most recent comment below it is claimed that the generated function cannot be called. That is false.

 edd@rob:/tmp$ editor demo20200408/R/foo.R # subst. fave editor here edd@rob:/tmp$ cat demo20200408/R/foo.R r_hello_world <- function() { cat("hi there\n") ignored <- rcpp_hello_world() NULL } edd@rob:/tmp$ R CMD INSTALL demo20200408 * installing to library '/usr/local/lib/R/site-library' * installing *source* package 'demo20200408'... ** using staged installation ** libs make: Nothing to be done for 'all'. installing to /usr/local/lib/R/site-library/00LOCK-demo20200408/00new/demo20200408/libs ** R ** byte-compile and prepare package for lazy loading ** help *** installing help indices ** building package indices ** testing if installed package can be loaded from temporary location ** checking absolute paths in shared objects and dynamic libraries ** testing if installed package can be loaded from final location ** testing if installed package keeps a record of temporary installation path * DONE (demo20200408) edd@rob:/tmp$ Rscript -e 'library(demo20200408); r_hello_world()' hi there NULL edd@rob:/tmp$

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM