You are on page 1of 4

Home

Brian J. Knaus
Brian J. Knaus’s blog about genomics and biology.

Header files in Rcpp About


Mon Aug 14, 2017 by Brian J. Knaus in  R  R, Rcpp, Header files Evolutionary genomics,
quantitative and
In C++ you can create functions in order to help organize your code. This is helpful computational biology.
as your project grows or if you have a task that is performed by a function that
several other functions may call. However, the functions you create are only visible
to the other funcitons that are contained in a single source file. As your project Recent Posts
grows, you may want to distribute your functions among several files. And if you do Getting started with
create that funcitons that is called by several other functions you may want to put it Rcpp
in its own file. But how do you get functions in different files to communicate with Analysis of variance
one another? The answer is to create header files. This post demonstrates how to The linear model
create and use header files within the Rcpp framework. A minimal Rcpp and
Roxygen2 package
A minimal R package Header files in Rcpp

The use of header files is best illustrated by adding them to an R package. In order
to illustrarte their use, we’ll need to create a minimal R package to work with. I
suggest using the R package pkgKitten which can be installed from CRAN if you do Links
not already have it. This site on GitHub
vcfR
R> library(pkgKitten)
vcfR on GitHub
R> kitten(name = "myRpackage")

Once we’ve created our package we can validate that it passes CRAN tests as
follows.

bash$ R CMD build myRpackage


bash$ R CMD check --as-cran myRpackage_1.0.tar.gz

I generate one NOTE.

* checking CRAN incoming feasibility ... NOTE


Maintainer: ‘Your Name <your@email.com>’

New submission

For the purposes of this example, we can ignore this NOTE.

Header and source files


We’re now ready to add our header and source files. First, we’ll use devtools to
easily add Rcpp to the package.

bash$ cd myRpackage
bash$ R
R> library(devtools)
R> use_rcpp()
You’ll want to follow the directions at the prompt. My solution was to add lines to
the hello.R file. I’ve also modified this file from the one created by pkgKitten to
include Roxygen comments.

File: R/hello.R

#' @title hello


#' @description
#' Says hello.
#' @name hello
#' @param txt something to say hello to
#'
#' @export
hello <- function(txt = "world") {
cat("Hello, ", txt, "\n")
}

#' @useDynLib myRpackage


#' @importFrom Rcpp sourceCpp
NULL

We can now add a header file as well as some Rcpp code files to our package. We’ll
add a total of three files. The first file will be named modString.h. This is our header
file and it declares our function. The second file will be named modString.cpp. This is
the function that is declared in the header file. Lastly, we’ll create myFunction.cpp.
This is Rcpp code that will call the function that is declared in the header file. These
files are presented below.

File: modString.h

#ifndef MODSTRING_H
#define MODSTRING_H

#include <Rcpp.h>
Rcpp::StringVector modString(Rcpp::StringVector myStringV);

#endif

Note the inclusion of the following code.

#ifndef MODSTRING_H
#define MODSTRING_H
...
#endif

This is the ‘header guard’ and protects you from making multiple definitions of this
code. This should always be a part of your header files.

File: modString.cpp

#include <string>
#include <sstream>
#include <Rcpp.h>

Rcpp::StringVector modString(Rcpp::StringVector myStringV)


{
if(myStringV.size() > 1){
myStringV[1] = "Rcpp";
}
return myStringV;
}

File: myFunction.cpp
#include <Rcpp.h>
#include "modString.h"

//' @title myFunction


//' @description
//' Modify a string in Rcpp.
//' @name myFunction
//' @param x a vector of strings
//' @examples
//' myFunction(x=c('Hello', "C++", 'header', 'files'))
//'
//' @export
// [[Rcpp::export]]
Rcpp::StringVector myFunction(Rcpp::StringVector x) {
x = modString(x);
return x;
}

NAMESPACE file
The pkgKitten creates a NAMESPACE file for us. However, I like to use the Roxygen
functionality to manage my NAMESPACE files. Because the pkgKitten NAMESPACE
file was not created using Roxygen it will complain when we use
devtools::document(). This is a problem because we do need to export the function
we created to our namespace. I suggest creating your own NAMESPACE file as
illustrated below. Once you’ve created this file it will be updated by Roxygen when
documenting your package.

FILE: NAMESPACE

# Generated by roxygen2: do not edit by hand

export(hello)
export(myFunction)
importFrom(Rcpp,sourceCpp)
useDynLib(myRpackage)

Because we’ve added Roxygen comments to the hello.R file, we’ll want to remove its
*.Rd so that Roxygen can generate one. Then we’ll want to document the project
using devtools.

bash$ rm man/hello.Rd
bash$ R
R> devtools::document()
R> q()
bash$ cd ..

We should now be able to build and check our code.

bash$ R CMD build myRpackage


bash$ R CMD check --as-cran myRpackage_1.0.tar.gz

I generate the same NOTE mentioned above, and we can ignore it again.

Usage
We should now be able to install our package and test it.

R> install.packages("myRpackage_1.0.tar.gz", repos = NULL, type="source")


R> library('myRpackage')
R> myFunction(x=c('Hello', "C++", 'header', 'files'))
The function modString replaces the second element of the vector, “C++”, with
“Rcpp”. This demonstrates functionality of our header file. We can now use
functions from different files together.

Links
These are sources for information I used to create this post.

Headers and Includes at cplusplus.com.


Header files at LearnCpp.com.
pkgKitten at CRAN, and at dirk.eddelbuettel.com (because it has a cute picture).

In order to find examples of header files used in R packages you can search GitHub
using the following query.

user:cran extension:.h

Make sure you search for ‘Code’ instead of the default search of ‘Repositories’ so
that you return code examples.

Share
   
2 Comments knausb.github.io 
1 Login

 Recommend 1 t Tweet f Share Sort by Best

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

Øystein Sørensen • 2 years ago


This blog post was exactly what I needed to split up my >1000-line cpp file :-)
Thanks!
△ ▽ • Reply • Share ›

Brian J. Knaus Mod > Øystein Sørensen • 2 years ago


Good to hear it helped someone. Thanks!
△ ▽ • Reply • Share ›

✉ Subscribe d Add Disqus to your siteAdd DisqusAdd 🔒 Disqus' Privacy PolicyPrivacy PolicyPrivacy

Blog contents © Brian J. Knaus

Back to top

You might also like