mirror of https://github.com/swig/swig
375 lines
9.6 KiB
HTML
375 lines
9.6 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and R</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff">
|
|
<H1><a name="R">34 SWIG and R</a></H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#R_nn2">Bugs</a>
|
|
<li><a href="#R_nn3">Using R and SWIG</a>
|
|
<li><a href="#R_nn4">Precompiling large R files</a>
|
|
<li><a href="#R_nn5">General policy</a>
|
|
<li><a href="#R_language_conventions">Language conventions</a>
|
|
<li><a href="#R_nn6">C++ classes</a>
|
|
<ul>
|
|
<li><a href="#R_class_examples">Examples</a>
|
|
</ul>
|
|
<li><a href="#R_nn7">Enumerations</a>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<p>
|
|
R is a GPL'ed open source statistical and plotting environment.
|
|
Information about R can be found at <a
|
|
href="https://www.r-project.org/">www.r-project.org</a>.
|
|
</p>
|
|
|
|
<p>
|
|
The R bindings are under active development. They have been used to
|
|
compile and run an R interface to QuantLib running on Mandriva Linux
|
|
with gcc. They are also used to create the SimpleITK R package, which
|
|
runs on Linux and MacOS. SWIG is used to create all wrapper
|
|
interfaces
|
|
to <a href="https://www.simpleitk.org/">SimpleITK</a>. The R
|
|
bindings also work on Microsoft Windows using Visual C++.
|
|
</p>
|
|
|
|
<H2><a name="R_nn2">34.1 Bugs</a></H2>
|
|
|
|
|
|
<p>
|
|
Currently the following features are not implemented or broken:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>Garbage collection of some created objects. Finalizers are
|
|
available for wrapped C++ classes and are called by the
|
|
garbage collection system.
|
|
<li>C Array wrappings
|
|
</ul>
|
|
|
|
<H2><a name="R_nn3">34.2 Using R and SWIG</a></H2>
|
|
|
|
|
|
<p>
|
|
To use R and SWIG in C mode, execute the following commands where
|
|
example.c is the name of the file with the functions in them
|
|
</p>
|
|
|
|
<div class="shell">
|
|
<pre>
|
|
swig -r example.i
|
|
R CMD SHLIB example_wrap.c example.c
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The corresponding options for C++ mode are
|
|
</p>
|
|
|
|
<div class="shell">
|
|
<pre>
|
|
swig -c++ -r -o example_wrap.cpp example.i
|
|
R CMD SHLIB example_wrap.cpp example.cpp
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
Note that R is sensitive to the names of the files.
|
|
The name of the wrapper file must be the
|
|
name of the library unless you use the -o option to R when building the library, for example:
|
|
</p>
|
|
|
|
<div class="shell">
|
|
<pre>
|
|
swig -c++ -r -o example_wrap.cpp example.i
|
|
R CMD SHLIB -o example.so example_wrap.cpp example.cpp
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
R is also sensitive to the name of the file
|
|
extension in C and C++ mode. In C++ mode, the file extension must be .cpp
|
|
rather than .cxx for the R compile command to recognize it. If your C++ code is
|
|
in a file using something other than a .cpp extension, then it may still work using PKG_LIBS:
|
|
</p>
|
|
|
|
<div class="shell">
|
|
<pre>
|
|
swig -c++ -r -o example_wrap.cpp example.i
|
|
PKG_LIBS="example.cxx" R CMD SHLIB -o example example_wrap.cpp
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The commands produces two files. A dynamic shared object file called
|
|
example.so, or example.dll, and an R wrapper file called example.R. To load these
|
|
files, start up R and type in the following commands
|
|
</p>
|
|
|
|
<div class="shell">
|
|
<pre>
|
|
dyn.load(paste("example", .Platform$dynlib.ext, sep=""))
|
|
source("example.R")
|
|
cacheMetaData(1)
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The cacheMetaData(1) will cause R to refresh its object tables.
|
|
Without it, inheritance of wrapped objects may fail.
|
|
These two files can be loaded in any order.
|
|
</p>
|
|
|
|
<p>
|
|
If you are compiling code yourself (not using R itself), there are a few things to watch out for:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>The output shared library name (to the left of the file extension) MUST match the module name, or alternatively, you can also set the -package NAME command line argument. See swig -r -help for more information
|
|
<li>If you do not set the output file name appropriately, you might see errors like
|
|
<div class="shell">
|
|
<pre>
|
|
> fact(4)
|
|
Error in .Call("R_swig_fact", s_arg1, as.logical(.copy), PACKAGE = "example") :
|
|
"R_swig_fact" not available for .Call() for package "example"
|
|
</pre>
|
|
</div>
|
|
<li>Make sure the architecture of the shared library(x64 for instance), matches the architecture of the R program you want to load your shared library into
|
|
</ul>
|
|
|
|
<H2><a name="R_nn4">34.3 Precompiling large R files</a></H2>
|
|
|
|
|
|
<p>
|
|
In cases where the R file is large, one make save a lot of loading
|
|
time by precompiling the R wrapper. This can be done by creating the
|
|
file makeRData.R which contains the following
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
source('BigFile.R')
|
|
save(list=ls(all=TRUE), file="BigFile.RData", compress=TRUE)
|
|
q(save="no")
|
|
</pre></div>
|
|
|
|
<p>
|
|
This will generate a compiled R file called BigFile.RData that
|
|
will save a large amount of loading time.
|
|
</p>
|
|
|
|
<p>
|
|
There is no need to precompile large R files if the SWIG-generated code is being included
|
|
in an R package. The package infrastructure provides this service during package installation.
|
|
</p>
|
|
|
|
<H2><a name="R_nn5">34.4 General policy</a></H2>
|
|
|
|
|
|
<p>
|
|
The general policy of the module is to treat the C/C++ as a basic
|
|
wrapping over the underlying functions and rely on the R type system
|
|
to provide R syntax.
|
|
</p>
|
|
|
|
<H2><a name="R_language_conventions">34.5 Language conventions</a></H2>
|
|
|
|
|
|
<p>
|
|
getitem and setitem use C++ conventions (i.e. zero based indices). [<-
|
|
and [ are overloaded to allow for R syntax (one based indices and
|
|
slices)
|
|
</p>
|
|
|
|
<H2><a name="R_nn6">34.6 C++ classes</a></H2>
|
|
|
|
|
|
<p>
|
|
Wrapping of C++ classes for R works quite well. R has a special
|
|
type, known as an external reference, that can be used as a pointer
|
|
to arbitrary things, including C++ classes. The proxy layers generated
|
|
for other classes are not required.
|
|
</p>
|
|
|
|
<p>
|
|
SWIG currently creates a custom hierarchy of R classes derived from the
|
|
external reference type and implements
|
|
type checking and function overloading in the R code it generates. In
|
|
the future we hope to utilise the built in R6 class structures.
|
|
</p>
|
|
|
|
<p>
|
|
The R interface has the following capabilities:
|
|
</p>
|
|
<ul>
|
|
<li> Destructor methods are registered and called automatically by the R garbage collector.
|
|
<li> A range of std::vector types are converted automatically to R equivalents via the std_vector.i library.
|
|
<li> The $ operator is used for method access.
|
|
<li> Variable accessors are automatically generated and called via the $, [, [[, $<-, [<-, [[<- operators.
|
|
</ul>
|
|
|
|
<H3><a name="R_class_examples">34.6.1 Examples</a></H3>
|
|
|
|
|
|
<p>
|
|
Consider the following simple example:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
class Vehicle {
|
|
private:
|
|
int m_axles;
|
|
|
|
public:
|
|
int Axles() {
|
|
return(m_axles);
|
|
}
|
|
|
|
bool Available;
|
|
|
|
Vehicle() {
|
|
Available=false;
|
|
m_axles=2;
|
|
}
|
|
|
|
Vehicle(int ax) {
|
|
Available=false;
|
|
m_axles=ax;
|
|
}
|
|
};
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
The following options are available in R:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
v1 <- Vehicle()
|
|
v2 <- Vehicle(4)
|
|
# access members
|
|
v1$Axles()
|
|
[1] 2
|
|
v2$Axles
|
|
[1] 4
|
|
v1$Available
|
|
[1] FALSE
|
|
# Set availability
|
|
v1$Available <- TRUE
|
|
v1$Available
|
|
[1] TRUE
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
A useful trick to determine the methods that are available is to
|
|
query the R method definition as follows:
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
# display the methods for the class
|
|
getMethod("$", class(v1))
|
|
|
|
Method Definition:
|
|
|
|
function (x, name)
|
|
{
|
|
accessorFuns = list(Axles = Vehicle_Axles, Available = Vehicle_Available_get)
|
|
vaccessors = c("Available")
|
|
idx = pmatch(name, names(accessorFuns))
|
|
if (is.na(idx))
|
|
return(callNextMethod(x, name))
|
|
f = accessorFuns[[idx]]
|
|
if (is.na(match(name, vaccessors)))
|
|
function(...) {
|
|
f(x, ...)
|
|
}
|
|
else f(x)
|
|
}
|
|
|
|
Signatures:
|
|
x
|
|
target "_p_Vehicle"
|
|
defined "_p_Vehicle"
|
|
|
|
</pre>
|
|
</div>
|
|
<p>
|
|
The names in the <tt>accessorFuns</tt> list correspond to class methods while names in the <tt>vaccessors</tt> section
|
|
correspond to variables that may be modified.
|
|
</p>
|
|
<H2><a name="R_nn7">34.7 Enumerations</a></H2>
|
|
|
|
|
|
<p>
|
|
R doesn't have a native enumeration type. Enumerations are represented
|
|
as character strings in R, with calls to R functions that convert back
|
|
and forth between integers.
|
|
</p>
|
|
|
|
<p>
|
|
The details of enumeration names and contents are stored in hidden R
|
|
environments, which are named according to the enumeration name - for
|
|
example, an enumeration colour:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
enum colour { red=-1, blue, green = 10 };
|
|
</pre></div>
|
|
|
|
<p>
|
|
will be initialized by the following call in R:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
defineEnumeration("_colour",
|
|
.values=c("red" = .Call('R_swig_colour_red_get',FALSE, PACKAGE='enum_thorough'),
|
|
"blue" = .Call('R_swig_colour_blue_get',FALSE, PACKAGE='enum_thorough'),
|
|
"green" = .Call('R_swig_colour_green_get',FALSE, PACKAGE='enum_thorough')))
|
|
</pre></div>
|
|
|
|
<p>
|
|
which will create an environment named <tt>.__E___colour</tt>. The enumeration
|
|
values are initialised via calls to C/C++ code, allowing complex
|
|
values for enumerations to be used. Calls to the C/C++ code require
|
|
the compiled library to be loaded, so a <tt>delayedAssign</tt> is employed
|
|
within <tt>defineEnumeration</tt> in order to allow the code to be easily used in R
|
|
packages.
|
|
</p>
|
|
|
|
<p>
|
|
The user typically does not need to access the enumeration lookup
|
|
functions or know the name of the enumeration type used by
|
|
R. Attributes containing the type information are attached by swig to
|
|
functions requiring enumeration arguments or returning enumeration
|
|
values, and those attributes are used to identify and access the
|
|
appropriate environments and thus translate between characters
|
|
and integers.
|
|
</p>
|
|
|
|
<p>
|
|
The relevant functions, for debugging purposes, are <tt>enumToInteger</tt> and
|
|
<tt>enumFromInteger</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
Anonymous enumerations are ignored by the binding generation process,
|
|
leaving no way of accessing the value of anonymous enumerations from R
|
|
code.
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|