みんなのRcpp 35.4 (仮)
Rcppパッケージで外部C++ライブラリを使う
Using external C++ libraries in Rcpp packages

Watal M. Iwasaki   @heavywatal
SOKENDAI, The Graduate University for Advanced Studies
2018-12-01 Japan.R 2018

https://heavywatal.github.io/slides/japanr2018/

Rcpp: a bridge between R and C++

r_for = function(n) {
  s = 0; for (i in seq_len(n)) {s = s + 1 / i}; s
}
r_vec = function(n) sum(1 / seq_len(n))

Rcpp::cppFunction("double rcpp(int n) {
  double s = 0; for (int i = 1; i <= n; ++i) {s += 1.0 / i;} return s;
}")  # Compilation takes a few seconds here

n = 1000000L
rbenchmark::benchmark(r_for(n), r_vec(n), rcpp(n))[,1:4]
      test replications elapsed relative
1 r_for(n)          100   3.968   29.835
2 r_vec(n)          100   0.473    3.556
3  rcpp(n)          100   0.133    1.000

⚡ Rcpp helps improving performance.
📦 ~1500 CRAN packages depend on Rcpp.
🎉 Happy 10th birthday and version 1.0.0 (2018-11-05).

Online resources for developing Rcpp packages

But lacking “how to use external libraries” 😢

Necessity is the mother of invention. Let’s do it 💪

Structure of a typical C/C++ library

Source repository:

evolution/
├── README.md
└── src/
    ├── individual.hpp      # header file for declaration
    ├── individual.cpp      # source file for definition
    ├── population.hpp
    └── population.cpp

Compiled and installed:

${PREFIX}/                  # e.g., /usr/local/
├── include/                # header files
│   └── evolution/
│       ├── individual.hpp
│       └── population.hpp
└── lib/
    └── libevolution.a      # shared library (.dylib, .dll)

Libraries can be header-only, e.g., Eigen, nlohmann/json.

Basic steps to incorporate C/C++ libraries

  • Write src/Makevars to instruct compilers and linkers:

    CXX_STD=CXX11
    PKG_CPPFLAGS=-DSTRICT_R_HEADERS -I/usr/local/include
    PKG_LIBS=-L/usr/local/lib -Wl,-rpath,/usr/local/lib -levolution
    
  • Use configure script to

    • Generate src/Makevars from a template src/Makevars.in.
    • Inspect build environments: OS, compilers, etc.
    • Detect installed libraries.
    • Do anything you want.
      e.g., git, cmake, etc.
http://r-pkgs.had.co.nz/src.html#make
https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Configure-and-cleanup

Various styles to incorporate C/C++ libraries

  • Find and use installed libraries. Fail if not found.
    • 😍 Simple. 😨 Requires users’ knowledge and effort.
    • e.g., xml2, magick, RcppGSL
  • Keep source code copies in inst/include/ and src/.
  • Fetch and track source codes with Git submodule
  • Find and use installed libraries. Install if not found.
    • 😍 Lean. Not requires users’ effort.
    • e.g., tumopp

Let’s discuss later 🍻

  • Any other ways to handle external C++ libraries?
  • Where to share these knowledge?
    • My own website
    • みんなのRcpp
    • Rcpp official documentation
  • How are Windows users doing?

Thank you for your attention 🤘