[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