Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Introduction
GNU Guile is a programming language “designed to help programmers create flexible applications that can be extended by users or other programmers with plug-ins, modules, or scripts”. It is an extension language platform, and contains an efficient compiler and virtual machine allowing both out of the box use for programs in Scheme, as well as integration with C and C++ programs.
Matías Guzmán Naranjo posed an almost-complete question on StackOverflow about how to combine Guile with R via Rcpp. It turns out that the code by Matías came from this gist showing both a Guile Scheme script, and a C use case example.
The Guile Scheme Script script.scm
This file is posted in this gist.
(define simple-func (lambda () (display "Script called, now I can change this") (newline))) (define quick-test (lambda () (display "Adding another function, can modify without recompilation") (newline) (adding-without-recompilation))) (define adding-without-recompilation (lambda () (display "Called this, without recompiling the C code") (newline)))
The C wrapper testguile.c
This file is also posted in this gist. We used (as
shown below) simpler link instructions which (on Ubuntu) can be ontained via guile-config link
and
are just -lguile-3.0 -lgc
on our Ubuntu 20.04 machine.
/* * Compile using: * gcc testguile.c \ * -I/usr/local/Cellar/guile/1.8.8/include \ * -D_THREAD_SAFE -L/usr/local/Cellar/guile/1.8.8/lib -lguile -lltdl -lgmp -lm -lltdl -o testguile */ #include <stdio.h> #include <libguile.h> int main(int argc, char** argv) { SCM func, func2; scm_init_guile(); scm_c_primitive_load("script.scm"); func = scm_variable_ref(scm_c_lookup("simple-func")); func2 = scm_variable_ref(scm_c_lookup("quick-test")); scm_call_0(func); scm_call_0(func2); return 0; }
The Rcpp Caller
This is an edited and updated version of Matías’ initial file.
#include <Rcpp.h> #include <stdio.h> #include <libguile.h> using namespace Rcpp; // [[Rcpp::export]] int test_guile(std::string file) { SCM func, func2; scm_init_guile(); scm_c_primitive_load(file.c_str()); func = scm_variable_ref(scm_c_lookup("simple-func")); func2 = scm_variable_ref(scm_c_lookup("quick-test")); scm_call_0(func); scm_call_0(func2); return 0; }
The System Integration
On our Ubuntu 20.04 box, Guile 3.0 is well supported and is easy installable. Header files are in a
public location, as are the library files. The configuration helper guile-config
(also
guile-config-3.0
to permit continued use of 2.2 and 2.0) provides the required compiler and linker
flags which we simply hardwired into src/Makevars
. A proper package would need to discover these
from a script, typically configure
, or Makefile
invocations. We leave this for another time; if
anybody reading this is interested in taking this further please get in touch.
PKG_CXXFLAGS = -I"/usr/include/guile/3.0" PKG_LIBS = -lguile-3.0 -lgc
Package
The rest of package was created via one call Rcpp.package.skeleton("RcppGuile")
after which we
- simply copied in the C++ file above into
src/guile.cpp
; - added the
src/Makevars
snippet above; and - copied in the example Scheme scripts as
inst/guile/script.scm
and that’s it! Then any of the usual steps with R will build and install a working package.
The complete package is available in this directory.
Guile Demo
The package can be used as follows, retrieving the Scheme script from within the package and clearly running it:
> library(RcppGuile) > test_guile(system.file("guile", "script.scm", package="RcppGuile")) Script called, now I can change this Adding another function, can modify without recompilation Called this, without recompiling the C code [1] 0 >
GNU Guile is made for building extensions. This short note showed how easy it is to connect R with Guile via a simple Rcpp package.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.