Skip to content

Commit

Permalink
Refresh package example (#1)
Browse files Browse the repository at this point in the history
* Re-org file names

* Fix package documentation

* Update package structure

* Switch RStudio project name and update RcppExports

* Remove Makevars as that is an artifact of the RcppArmadillo example and fix comment.

* Add implementation details

* Enable travis
  • Loading branch information
coatless authored Aug 20, 2018
1 parent d3a0976 commit 96b0bf2
Show file tree
Hide file tree
Showing 25 changed files with 362 additions and 174 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
^.*\.Rproj$
^\.Rproj\.user$
^\.travis\.yml$
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# R for travis: see documentation at https://docs.travis-ci.com/user/languages/r

language: R
sudo: false
cache: packages
23 changes: 14 additions & 9 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
Package: anRpackage
Package: SrcDir
Type: Package
Title: What the package does (short line)
Version: 1.0
Date: 2015-03-10
Author: Who wrote it
Maintainer: Who to complain to <yourfault@somewhere.net>
Description: More about what it does (maybe more than one line)
License: What license is it under?
Title: Embedding Multiple Code Files in Src
Version: 0.0.0.9000
Authors@R: person("James", "Balamuta", email = "balamut2@illinois.edu", role = c("aut", "cre"))
Description: Provides an implementation showing how multiple compiled code
files in the `src` directory can be used.
BugReports: https://github.com/r-pkg-examples/rcpp-headers-src
Depends: R (>= 3.4.0)
Imports: Rcpp (>= 0.11.5)
LinkingTo: Rcpp, RcppArmadillo
LinkingTo: Rcpp
License: GPL (>= 2)
Encoding: UTF-8
LazyData: true
RoxygenNote: 6.1.0
Roxygen: list(markdown = TRUE)
10 changes: 7 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
useDynLib(anRpackage)
importFrom(Rcpp, evalCpp)
exportPattern("^[[:alpha:]]+")
# Generated by roxygen2: do not edit by hand

export(calc_A_routine)
export(calc_B_routine)
export(calc_modifications)
importFrom(Rcpp,sourceCpp)
useDynLib(SrcDir, .registration = TRUE)
39 changes: 32 additions & 7 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
# This file was generated by Rcpp::compileAttributes
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

testfunction <- function(x) {
.Call('anRpackage_testfunction', PACKAGE = 'anRpackage', x)
#' Package functions
#'
#' Functions listed here are derived from the exported _C++_ functions.
#' Note that all functions work even after being split into multiple separate
#' files.
#'
#' @param x Vector of Numeric Values with length \eqn{n}.
#'
#' @return A vector of numeric values with length \eqn{n}.
#'
#' @rdname exported_funcs
#' @export
#' @examples
#' my_vec = c(3.5, 8, -1.5, -2, 0, 42)
#' calc_modifications(my_vec)
calc_modifications <- function(x) {
.Call(`_SrcDir_calc_modifications`, x)
}

testfunctionA <- function(x) {
.Call('anRpackage_testfunctionA', PACKAGE = 'anRpackage', x)
#' @rdname exported_funcs
#' @export
#' @examples
#' my_vecA = c(881, 884, 1,2,-4)
#' calc_A_routine(my_vecA)
calc_A_routine <- function(x) {
.Call(`_SrcDir_calc_A_routine`, x)
}

testfunctionB <- function(x) {
.Call('anRpackage_testfunctionB', PACKAGE = 'anRpackage', x)
#' @rdname exported_funcs
#' @export
#' @examples
#' my_vecB = c(512,32, -1, 1.3, 5.9)
#' calc_B_routine(my_vecB)
calc_B_routine <- function(x) {
.Call(`_SrcDir_calc_B_routine`, x)
}

3 changes: 3 additions & 0 deletions R/SrcDir-package.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#' @useDynLib SrcDir, .registration = TRUE
#' @importFrom Rcpp sourceCpp
"_PACKAGE"
128 changes: 128 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
## Separating Compiled Code into Individual Units with Headers

[![Travis-CI Build Status](https://travis-ci.org/r-pkg-examples/rcpp-headers-src.svg?branch=master)](https://travis-ci.org/r-pkg-examples/rcpp-headers-src)

The `SrcDir` R package provides an example of using header files to split
apart functions into separate code files while still being able to use each
function.

In essence, this project shows how to go from:

```bash
src/
|-> large-code-file.cpp
```

to:

```bash
src/
|-> combined-routines.cpp
|-> routineA.cpp
|-> routineA.h
|-> routineB.cpp
|-> routineB.h
```

For further organization, see the [SubdirSrc](https://github.com/r-pkg-examples/rcpp-headers-subdirs)
package for an example of compiling code found in `src/` subdirectories
(e.g. `src/A`, `src/B`).

### Usage

To install the package, you must first have a compiler on your system that is
compatible with R. For help on obtaining a compiler consult either
[macOS](http://thecoatlessprofessor.com/programming/r-compiler-tools-for-rcpp-on-os-x/)
or
[Windows](http://thecoatlessprofessor.com/programming/rcpp/install-rtools-for-rcpp/)
guides.

With a compiler in hand, one can then install the package from GitHub by:

```r
# install.packages("devtools")
devtools::install_github("r-pkg-examples/rcpp-headers-src")
library("SrcDir")
```

### Implementation Details

Separating out code into different files requires the use of header files (`.h`).
Headers provide a way to share function definitions and preprocessor macros
between two or more _C++_ files (`.cpp`). Using the header inside of another
file requires the use of the `#include`
[preprocessor directive](https://en.wikipedia.org/wiki/Preprocessor),
which effectively "copies" the contents of the header into the other file.

Take for instance the [`routineA.cpp`](https://github.com/r-pkg-examples/rcpp-headers-src/blob/master/src/routineA.cpp) file.

```cpp
#include <Rcpp.h>
#include "routineA.h"

// [[Rcpp::export]]
Rcpp::NumericVector calc_A_routine(Rcpp::NumericVector x) {
Rcpp::NumericVector a = x - 4;
return a;
}
```
Note, there are two different kinds of `#include` used:
- `#include <header_system.h>`
- `<>` indicate a system header file found in system directories or supplied with `-I`.
- `Rcpp.h` is a system library as it is located outside of the project space.
- `#include "header_local.h"`
- `""` means the file resides in the working directory of the program.
For more details, please see [Section 2.1 Include Syntax](https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html#Include-Syntax)
of the [`gcc` documentation](https://gcc.gnu.org/onlinedocs/cpp/index.html#SEC_Contents).
The accompanying header file would be [`routineA.h`](https://github.com/r-pkg-examples/rcpp-headers-src/blob/master/src/routineA.h). The header would
contain the function definition for `calc_A_routine()` as it is the only
function declared within the file.
```cpp
// Defines a header file containing function signatures for functions in src/
// Protect signatures using an inclusion guard.
#ifndef routineA_H
#define routineA_H
Rcpp::NumericVector calc_A_routine(Rcpp::NumericVector x);
#endif
```

As the header contents is "copied", it is important to protect the function
definitions to ensure they are only included once. To prevent this from happening,
an [inclusion guard](https://en.wikipedia.org/wiki/Include_guard) is
used. By checking for whether a variable is defined with `#ifndef`, the header
file can be copied completely or skip the define portion. In short, the
design pattern for this can be succiently stated as:

```cpp
#ifndef myfilename_H
#define myfilename_H

// Contents here

#endif
```

From here, both routines A and B can be included inside a third file
such as [`combined-routines.cpp`](https://github.com/r-pkg-examples/rcpp-headers-src/blob/master/src/combined-routines.cpp). The inclusion statements would be:

```cpp
#include <Rcpp.h>

// Load directory header files
#include "routineA.h"
#include "routineB.h"

// additional code
```

## License

GPL (\>= 2)
1 change: 1 addition & 0 deletions test.Rproj → SrcDir.Rproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ LaTeX: pdfLaTeX
BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd,collate,namespace
22 changes: 22 additions & 0 deletions man/SrcDir-package.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 0 additions & 40 deletions man/anRpackage-package.Rd

This file was deleted.

33 changes: 33 additions & 0 deletions man/exported_funcs.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 0 additions & 50 deletions man/rcpparma_hello_world.Rd

This file was deleted.

1 change: 0 additions & 1 deletion src/Makevars

This file was deleted.

2 changes: 0 additions & 2 deletions src/Makevars.win

This file was deleted.

Loading

0 comments on commit 96b0bf2

Please sign in to comment.