[Rcpp-devel] Passing XPtr between functions

Charles Determan cdetermanjr at gmail.com
Wed Jun 24 18:08:33 CEST 2015


Many thanks Krzysztof, your suggestion works.  I can explicitly create a
'new' arma::mat object and pass the resulting XPtr between functions.  I
will work on making everything prettier and document for a submission to
Rcpp Gallery unless someone is aware of one that already exists that I
somehow overlooked.

// [[Rcpp::export]]
SEXP testXptr(NumericMatrix A)
{
    arma::mat *armaMat = new arma::mat(A.begin(),A.rows(), A.cols(), false);
    XPtr<arma::mat> pMat(armaMat);
    return(pMat);
}

// [[Rcpp::export]]
void testReturn(SEXP ptrA, int nr, int nc)
{
    XPtr<arma::mat> ptrB(ptrA);
    arma::mat B = arma::mat( (double *) ptrB->memptr(),
          nr,
          nc,
          false);
    B.print("copied matrix");
}

Regards,
Charles

On Wed, Jun 24, 2015 at 10:19 AM, Krzysztof Sakrejda <
krzysztof.sakrejda at gmail.com> wrote:

> Hi Charles, comments inline
>
> 2015-06-24 11:03 GMT-04:00 Charles Determan <cdetermanjr at gmail.com>:
>
>> The fastLm examples are nice but they don't contain anything relating to
>> passing an XPtr between functions.  Regarding your comment about making an
>> XPtr around arma::mat 'innards' I'm not sure I fully understand.  I tried
>> creating an XPtr around a arma::mat but no success on passing the object
>> between functions.  It still returns that ~zeros.
>>
>> // [[Rcpp::export]]
>> SEXP testXptr(SEXP A)
>> {
>>     arma::Mat<double> armaMat = as<arma::mat>(A);
>>     XPtr<arma::mat> pMat(&armaMat);
>>     return(pMat);
>> }
>>
>
> When testXptr returns, armaMat is gone so it doesn't matter what you do
> with pMat.  You need to use "new" to create armaMat and hand it over to
> XPtr as above.  Then XPtr is returned to R. When XPtr is returned to R it's
> protected from R's garbage collection by having a reference (reference?
> something like that) to it in R.  armaMat lives on since it was created
> with "new".  When you delete the XPtr in R, _it_ gets garbage-collected and
> the destructor for XPtr calls "delete" on armaMat.  Then armaMat is gone
> and you don't have a memory leak.  So the scheme is:
>
> 1) Create object of class Whatever in C++ using new.
> 2) Wrap object in XPtr<Whatever>
> 3) Return XPTr<Whatever> to R and save it to a variable.
> 4) Pass XPtr<Whatever> to any functions that need the object of class
> Whatever
> 5) When you don't need the object of class Whatever, remove
> XPtr<Whatever> from the R session
> 6) R does gc on XPtr<Whatever>, which has a destructor.
> 7) Destructor from XPtr<Whatever> does "delete" on object of class
> Whatever.
>
> Been a few months since I used this but I'm sure someone will correct me
> if I'm not quite right here.  There really ought to be (and might already
> be) an Rcpp gallery item about this process.  I'll sign up to make on later
> this summer :)
>
> Krzysztof
>
>
>
>>
>> // [[Rcpp::export]]
>> void testReturn(SEXP ptrA, int nr, int nc)
>> {
>>     XPtr<arma::mat> ptrB(ptrA);
>>     arma::mat B = arma::mat( (double *) ptrB->memptr(),
>>           nr,
>>           nc,
>>           false);
>>     B.print("copied matrix");
>> }
>>
>> Charles
>>
>> On Wed, Jun 24, 2015 at 8:32 AM, Dirk Eddelbuettel <edd at debian.org>
>> wrote:
>>
>>>
>>> On 24 June 2015 at 08:22, Charles Determan wrote:
>>> | Thank you John,
>>> |
>>> | I am familiar with bigmemory (I am one of the current developers
>>> actually).
>>> | The project I am working on doesn't need the shared memory aspect so
>>> was
>>> | intending to avoid the dependency and just leverage the more familiar
>>> and
>>> | developed Armadillo library.  However your response informs me that I
>>> did not
>>> | fully understand how armadillo objects are handled.  I have some other
>>> ideas
>>> | with how I can address my problem but this was something I was hoping
>>> to apply
>>> | both for this project and for the sake of learning.
>>>
>>> Look at more current RcppArmadillo examples, and in particular _all_ the
>>> variants of the fastLm benchmark in examples.  By doing the explicit
>>> cast,
>>> you _forced_ a copy which may then have destroyed the Xptr link.  I
>>> *think*
>>> you could just do XPtr around arma::mat innards.  I would actually be
>>> interested in having something somewhere between bigmemory (where I was
>>> one
>>> of the first external users) and what we have in RcppArmadillo.
>>>
>>> Dirk, during a break of Rcpp class in Zuerich
>>>
>>> | Regards,
>>> | Charles
>>> |
>>> | On Tue, Jun 23, 2015 at 9:29 PM, John Buonagurio <
>>> jbuonagurio at exponent.com>
>>> | wrote:
>>> |
>>> |     Hi Charles,
>>> |
>>> |     > SEXP testXptr(SEXP A)
>>> |     > {
>>> |     >     arma::Mat<double> armaMat = Rcpp::as<arma::Mat<double> >(A);
>>> |     >     Rcpp::XPtr<double> pMat(armaMat.memptr());
>>> |     >     return(pMat);
>>> |     > }
>>> |
>>> |     armaMat is on the stack, so the Armadillo memptr is no longer
>>> valid when
>>> |     you return from the testXptr function.
>>> |
>>> |     One simple solution in your case would be to dynamically allocate
>>> with
>>> |     "new" [e.g. arma::mat *A = new arma::mat(...);], though I can't
>>> tell you
>>> |     off hand how object lifetime is managed with Armadillo objects.
>>> |
>>> |     If you're trying to preserve a matrix across function calls in R,
>>> have you
>>> |     looked into bigmemory? http://gallery.rcpp.org/articles/
>>> |     using-bigmemory-with-rcpp/
>>> |
>>> |     John
>>> |
>>> |
>>> |
>>> | _______________________________________________
>>> | Rcpp-devel mailing list
>>> | Rcpp-devel at lists.r-forge.r-project.org
>>> |
>>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>>
>>> --
>>> http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
>>>
>>
>>
>> _______________________________________________
>> Rcpp-devel mailing list
>> Rcpp-devel at lists.r-forge.r-project.org
>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20150624/73793e6b/attachment.html>


More information about the Rcpp-devel mailing list