Skip to content

Latest commit

 

History

History
117 lines (79 loc) · 3.86 KB

README.md

File metadata and controls

117 lines (79 loc) · 3.86 KB

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: