Skip to content
What the Package Does (One Line, Title Case)
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
R Pass cran check Jul 2, 2019
inst/include
man
src `cexport_api.h` -> `cexport.h` Jul 2, 2019
.Rbuildignore README Jul 2, 2019
.gitignore Initial commit Jul 2, 2019
DESCRIPTION Pass cran check Jul 2, 2019
LICENSE
LICENSE.md
NAMESPACE Pass cran check Jul 2, 2019
README.Rmd `cexport_api.h` -> `cexport.h` Jul 2, 2019
README.md `cexport_api.h` -> `cexport.h` Jul 2, 2019
cexport.Rproj

README.md

cexport

This README holds an example of:

  • Creating a C function that you can call from R.

  • “Registering” that C callable to be called from another package’s C code.

  • “Getting” the registered C callable and providing an easy header file for other packages to use.

  • Actually calling that function from another package’s C code.

This package implements, registers, and exports the function that will be called in other packages.

The other package that goes along with this one and actually calls the C function from it’s own C code is cexportuser.

You can install this package with:

devtools::install_github("DavisVaughan/cexport")

You can install the companion package that uses this C code (which should “just work” and also install cexport if needed) with:

devtools::install_github("DavisVaughan/cexportuser")

Details

Here are the steps to do this yourself:

  • Create your C function (src/arith.c - cexport_plus_one())

  • Optionally export it to R with the standard R_registerRoutines() (src/init.c) and #' @useDynLib cexport, .registration = TRUE (cexport-package.R).

  • “Register” the C callable with R_RegisterCCallable() so other packages can find it with R_GetCCallable() (src/init.c).

  • At this point, you can either let users call R_GetCCallable() themselves in their own package, or you can be nice and generate a header file that they can just #include to get access to your API.

  • Let’s be nice. In inst/include/cexport.h we create an API function with essentially the same signature as our original function, look up the C callable once, and call the function.

    • We also make the function static so that users can call it from multiple of their C files without throwing any “duplicate symbol” errors.

    • And we R_INLINE the function to reduce the overhead of the C function call. Essentially, once we have called the function once to get the C callable from cexport, repeated calls to the function will be just as fast as calling it natively.

  • Now install the package.

The next section will be from the perspective of a package that is going to be calling cexport_plus_one() from their own C code. That package is cexportuser.

  • In the package that is going to be calling cexport_plus_one(), add LinkingTo: cexport.

  • Now also add Imports: cexport. This is required as you have to fully load cexport to be able to use its C callables.

  • You must also @importFrom something from cexport so it gets loaded. I imported the plus_one() function (cexportuser-package.R).

  • Create your C function that is going to call cexport_plus_one(). At the top of the file put #include <cexport.h>. RStudio should recognize this for you. You can now call cexport_plus_one(). (src/arith.h - cexportuser_plus_two()).

  • Export the C function to R if you want (src/init.c, exported as plus_two() in arith.R).

If all goes well you should be able to do something like:

library(cexportuser)
plus_two(2L)
#> [1] 4

References

A few packages do this, with cleancall probably being the easiest to read:

Also R Extensions has some advice:

And there is some information in R Packages:

You can’t perform that action at this time.