Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/davisvaughan/cexport
What the Package Does (One Line, Title Case)
https://github.com/davisvaughan/cexport
Last synced: 11 days ago
JSON representation
What the Package Does (One Line, Title Case)
- Host: GitHub
- URL: https://github.com/davisvaughan/cexport
- Owner: DavisVaughan
- License: other
- Created: 2019-07-02T19:24:43.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2019-07-02T23:11:13.000Z (over 5 years ago)
- Last Synced: 2024-10-09T22:11:02.734Z (28 days ago)
- Language: C
- Size: 21.5 KB
- Stars: 32
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
editor_options:
chunk_output_type: console
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# 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](https://github.com/DavisVaughan/cexportuser).
You can install this package with:
```{r, eval=FALSE}
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:
```{r, eval = FALSE}
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](https://github.com/DavisVaughan/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 `. 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:
```{r}
library(cexportuser)
plus_two(2L)
```# References
A few packages do this, with `cleancall` probably being the easiest to read:
- [cleancall](https://github.com/r-lib/cleancall/)
- [bdsmatrix](https://github.com/cran/bdsmatrix)
- [xts](https://github.com/joshuaulrich/xts)Also R Extensions has some advice:
- https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Linking-to-native-routines-in-other-packages
And there is some information in R Packages:
- [Exporting C Code](https://r-pkgs.org/src.html#c-export)
- [Importing C Code](https://r-pkgs.org/src.html#c-import)