[Rd] How difficult is it to wrap a large C++ library with R?

Douglas Bates dmbates at gmail.com
Mon Jul 4 23:08:35 CEST 2005

On 7/4/05, Bo Peng <ben.bob at gmail.com> wrote:
> > > * Wrap C++ class hierarchy. Virtual functions need to be supported.
> > > (SWIG can generate Python shadow classes that behave almost exactly
> > > like the underlying C++ classes)
> >
> > This is hard to do in R, because the R object model is quite different
> > from that of C++ (whereas Python's is more similar).
> I guess I will have to learn R OOP in detail first. It would be
> terrible if I will have to re-write every C++ class in R (and without
> inheritance)!

What makes you think that there is no inheritance of classes in R?
> > > * Direct access to C++ data structure. For example, an object may keep
> > > a C array internally. I will need a method (maybe wrap this data into
> > > a R object) to read/write this array directly.
> >
> > That's not too hard provided you use C++ code to do the actual access.
> > That is, you write an R function that calls C++ code to do the work.
> > It's a lot harder if you want to keep it all in R, because it doesn't
> > understand C++ type definitions, alignment conventions, etc.
> So this has to be done through functions. In Python, I can create an
> object to wrap C array that can be accessed just like regular list. I
> guess it would be difficult to create a new data type in R.
> Anyway, where can I find the most complete information about
> implementation of R/OOP at C/C++ level? (Or should I write classes in
> R and call C++ functions for every member function?) I have not read
> http://cran.r-project.org/doc/manuals/R-exts.pdf in detail but my
> impression is that almost everything is done at a function (not
> object) level using .C().

Well the R object model is based on generic functions and methods are
functions.  The S4 class structure differs from the S3 structure in
that there is a formal definition of an S4 class but not for an S3
class.  However, even in S4, methods do not belong to a class. 
Methods are intermediate to classes and generic functions and are
associated with a signature for the arguments of the generic function.

If you want to be able to use S4 classes effectively you should use
the .Call interface to compiled code and not the .C interface.  If you
pass a classed object through the .Call interface to compiled code you
can extract or set the values of slots in the object through the
GET_SLOT and SET_SLOT macros.  Admittedly this is not as convenient
for the C++ programmer as being able to pass a pointer to an object
from a C++ class but it does make it easier to think of objects in R
and the corresponding objects in compiled code.  The Matrix package on
CRAN contains many examples of this use of this technique.

Another technique that you may want to consider is the use of
ExternalPointers.  If you examine the C source file lmer.c from the
aforementioned Matrix package you will see where I create a pointer to
a C struct in the compiled code and pass it back to R so it can later
be passed to the C code and I can extract the struct.  The same could
be done for an instance of a C++ class.

More information about the R-devel mailing list