[Rd] Create and access several instances of a C++ class from R

Dirk Eddelbuettel edd at debian.org
Sat May 7 02:39:58 CEST 2011


Sören and Carlo,

On 6 May 2011 at 19:24, soeren.vogel at uzh.ch wrote:
| Hello
| 
| We have a C++ class with several methods that manipulate an object. How is
| it possible to create several instances of that class *from R* in the C++
| realm, which can then be accessed via a given name character? 

Yes it is, and even somewhat easily given Rcpp modules as we tried to explain
over at the Rcpp-devel list when you asked there.  As a real quick
proof-of-concept, I did the following:


1) Make sure you have a recent Rcpp such as 0.9.3 or 0.9.4


2) Let Rcpp create a complete 'stub' of a working package with Rcpp modules
   support for you via the Rcpp.package.skeleton.function() with the
   module=TRUE argument:


   R> library(Rcpp)
   R> Rcpp.package.skeleton("simple", module=TRUE)
   Creating directories ...
   Creating DESCRIPTION ...
   Creating NAMESPACE ...
   Creating Read-and-delete-me ...
   Saving functions and data ...
   Making help files ...
   Done.
   Further steps are described in './simple/Read-and-delete-me'.
   
   Adding Rcpp settings
    >> added RcppModules: yada
    >> added Depends: Rcpp
    >> added LinkingTo: Rcpp
    >> added useDynLib directive to NAMESPACE
    >> added Makevars file with Rcpp settings
    >> added Makevars.win file with Rcpp settings
    >> added example header file using Rcpp classes
    >> added example src file using Rcpp classes
    >> added example R file calling the C++ example
    >> added Rd file for rcpp_hello_world
    >> copied the example module 
   R> 

   
3) As you are keen to see that we get actual new objects, I am just doing
   the minimal code for by adding one for a new class member function:

    void showmyaddress() const { std::cout << "Address is " << this << std::endl; }

   which I add to the class 'World' in file simple/src/rcpp_module.rcpp -- on
   line 32 if it matters.   I also add this line to the module definition in
   the same file on line 62:

     .const_method( "showmyaddress", &World::showmyaddress, "get *this ptr address")

   It doesn't matter that the method is const, you can do without const in
   both eg

    void showmyaddress() { std::cout << "Address is " << this << std::endl; }

    .method( "showmyaddress", &World::showmyaddress, "get *this ptr address")

   All that the code does is reveal its pointer to stdout.


4) Install it via

   $ R CMD INSTALL simple


5) Try it in R (and I first

   R> library(simple)
   Loading required package: Rcpp
   R> World
   C++ class 'World' <0x2b84940>
   Constructors:
       World()
   
   Fields: No public fields exposed by this class
   
   Methods: 
        std::string greet()  
              docstring : get the message
        void set(std::string)  
              docstring : set the message
        void showmyaddress()  const 
              docstring : get *this ptr address
   R>
   R> w1 <- new( World )
   R> w1$showmyaddress()
   Address is 0x2748370
   R>
   R> w2 <- new( World )
   R> w2$showmyaddress()
   Address is 0x2f960b0
   R> 
   

   so w1 and w2 are indeed objects of class World which live in different
   memory locations.

This should show the mechanics.  This is somewhat easy -- especially if you
know some C++ where it then helps you from having to write boiler plate code.
If you are relatively new to C and C++, it can be a little tougher.  Either
way, to my mind it is shorter (and I'd argue, easier) than anything you could
do in plain C with the standard R API.

Good luck, and please bring Rcpp questions to rcpp-devel.

Regards, Dirk



| Symbolic example (we hope this illustrates our problem):
| 
| // C++ side:
| class Foo{
| ...
| }
| // perhaps:
| void my_new_instance_wrapper("the_character") // plain to see that I am no C++ programmer ;-)
| {
|   static Foo "the_character"; // no return needed since we know the name of the instance = "the_character"
| }
| 
| # R side:
| create_new_instance <- function(name){
|   dono_what_to_use_here(???, class)
| }
| # perhaps:
| create_new_instance <- function(name){
|   .C("my_new_instance_wrapper", as.character(name))
| }
| 
| dyn.load("Foo")
| obj1 <- create_new_instance("bar", class="Foo")
| obj2 <- create_new_instance("baz", class="Foo")
| str(obj1)
| : character which can be manipulated using class methods in the C++ realm
| 
| What we do not want: make simple copies of the object in R; use Rcpp modules (we tried that without success, pointers in constructors cause trouble); re-write our code such that C++ only "works off" heavy code, the rest is R-side. What we want: interfacing (from the R-side) instances of our class where the instances exist in the C++ realm.
| 
| Either there is a function (or code) in R that solve this task, perhaps by returning pointers to instances of C++ classes. (Or there is a possibility to create a wrapper in C++ creating a new instance, the wrapper we do not know of.)
| 
| Thanks for any notes, tips, experiences.
| 
| Sören and Carlo
| 
| ______________________________________________
| R-devel at r-project.org mailing list
| https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
Gauss once played himself in a zero-sum game and won $50.
                      -- #11 at http://www.gaussfacts.com



More information about the R-devel mailing list