forked from hadley/r-pkgs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrc.rmd
85 lines (56 loc) · 2.58 KB
/
src.rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
---
layout: default
title: Compiled code
output: bookdown::html_chapter
---
# Compiled code {#src}
* Makefiles beyond the scope of this book.
* Bundling external libraries beyond the scope of this book (but I wish it
wasn't).
* Assumes that you know how to use C or C++ already. If you don't, see the
"Advanced R book" (online, amazon).
## C++
Easiest way to access compiled language from R is to use C++.
## C
Sometimes needed if you're wrapping old code, or you really need to eke out performance by avoiding C++ wrappers (this is rare). Mostly important for understand older packages.
* `.c` files in `src/`, need:
```c
#include <R.h>
#include <Rdefines.h>
```
* Need wrapper functions like this:
```{r, eval = FALSE}
#' @useDynLib qstack car
car_ <- function(x) .Call(car, x)
```
Speed considerations: <http://cran.r-project.org/doc/manuals/R-exts.html#Speed-considerations>
* Slowest: use `.Call("car")`
* Faster: use `.Call(car)`
* Fastest: don't write wrapper function
This makes microseconds of difference, so normally not important. Only matters if you have tight loop calling millions of times - and you can normally move that loop into C.
If you use `useDynLib`, you also need to add a `.onUnload()` function that cleans up after yourself.
```{r}
.onUnload <- function (libpath) {
library.dynam.unload("qstack", libpath)
}
```
## Fortran
Fortran 77 subroutines are directly callable via `.Fortran()`, though as with `.C()`, this is inefficient. The best way to use
Fortran code with R is to write a C wrapper callable by the `.Call()` interface (as described above). This of course
requires that the Fortran code can be called by C. For portability, this generally means either using a non-module
subroutine, or using the Fortran 2003 iso_c_binding module and providing an appropriate interface.
For more information about Fortran interfaces and mixing C and Fortran, see *Modern Fortran Explained*, by Metcalf, Reid, and Cohen.
## Java
See rJava. Unlike C and C++ wrappers, must always copy. This usually makes it unacceptably slow when working with larger data (which much of the time is why you're using an other language).
## Dynamically loading dll
Loading - use `@dynlib`.
To be good member of ecosystem, should also unload:
```{r, eval = FALSE}
.onUnload <- function(libpath) {
library.dynam.unload("yourpackagename", libpath)
}
```
This ensures that the DLL is unloaded if the package is unloaded.
## Licensing
If you're including code that someone else has written, you need to...
e.g. http://cran.rstudio.com/web/packages/optparse/COPYRIGHTS