[Rcpp-devel] Data Persistence when using inline

Darren Cook darren at dcook.org
Thu Sep 8 03:04:30 CEST 2011


> If the code was in pure C++, it would be trivial to have an object
> and then just pass a pointer to that object.  I can't figure out how
> to do the same thing with R+Rcpp+inline.

I asked myself a similar question a few weeks back (actually it came
from one of the questions at the end of the google talk [1] and, while
both Dirk and Romain confidently said it was possible, at the time I
couldn't see how to actually do it).

I think what you're looking for is Rcpp::XPtr. I.e. you have your C++
code allocate and *own* the memory, and then it passes it back to R by
wrapping it in XPtr. XPtr is a curious template as it does two distinct
tasks: it returns a C++ pointer to R, and it also turns an R object back
into a C++ pointer.

Below is the proof-of-concept example I came up with. I use a custom
class (the real point of this example), but it could just as well be
std::vector. This example also shows a couple of other things:

  1. Keeping the C++ class code in its own files.

  2. Compiling two functions at once; this isn't necessary for this
example, it is just quicker. (test5b.R is also included below, and shows
how to do this with two separate compiler invocations.)

(BTW, this example leaks memory. For long-running production code don't
forget that your C++ code owns the memory and is responsible for
deleting it.)

Darren

[1]: http://www.youtube.com/watch?v=UZkaZhsOfT4


--------- test5.R ---------------

library('inline')

header=paste(readLines("test5.h"),collapse="\n")
src=paste(readLines("test5.cpp"),collapse="\n")

use_src='
Rcpp::XPtr< Example > xp(xp_); //I.e. Example xp=xp_;
return wrap(xp->a + xp->b);
'

fun=cxxfunction(
    list(create=signature(),use=signature(xp_="externalptr")),
    list(create=src,use=use_src),
    includes=header,
    plugin="Rcpp"
    );

xp=fun$create()    #xp is an Example object
print(xp)
print(fun$use(xp))


-------- test5.h ------------------------

class Example{
public:
int a,b;

public:
Example(int a_,int b_):a(a_),b(b_){}

};

using namespace Rcpp;


-------- test5.cpp ------------------------

Example *xp=new Example(10,20);
return XPtr<Example>(xp,true);


-------- test5b.R --------------------------

library('inline')

header=paste(readLines("test5.h"),collapse="\n")
src=paste(readLines("test5.cpp"),collapse="\n")

use_src='
Rcpp::XPtr< Example > xp(xp_); //I.e. Example xp=xp_;
return wrap(xp->a + xp->b);
'

fun_create=cxxfunction(
    signature(),
    src,
    includes=header,
    plugin="Rcpp"
    );

fun_use=cxxfunction(
    signature(xp_="externalptr"),
    use_src,
    includes=header,
    plugin="Rcpp"
    );

xp=fun_create()    #xp is an Example object
print(xp)
print(fun_use(xp))




More information about the Rcpp-devel mailing list