On Wed, 24 May 2023 02:08:25 +0200 <pikappa.devel at gmail.com> wrote:> initialize = function() { > > .C("make_native_obj", self$native_obj) > > })> extern "C" void make_native_obj(double *obj) { > > auto native_obj = new NativeObjStruct(); > > memcpy(obj, &native_obj, sizeof(obj)); > > }> Is there a better way to do this?The .Call() interface (where functions take an arbitrary number of native R objects and return a native R object) combined with external pointers is likely to be a better approach here: https://cran.r-project.org/doc/manuals/R-exts.html#External-pointers-and-weak-references On the R side, the returned SEXP will have class 'externalptr', with not much to do about it programmatically. C code can additionally register a finalizer on the object in order to release the memory automatically after the it is discarded. -- Best regards, Ivan
Dirk Eddelbuettel
2023-May-24 14:16 UTC
[Rd] Heap access across multiple calls from R to C++
On 24 May 2023 at 09:09, Ivan Krylov wrote: | On Wed, 24 May 2023 02:08:25 +0200 | <pikappa.devel at gmail.com> wrote: | > Is there a better way to do this? | | The .Call() interface (where functions take an arbitrary number of | native R objects and return a native R object) combined with external | pointers is likely to be a better approach here: | | https://cran.r-project.org/doc/manuals/R-exts.html#External-pointers-and-weak-references Yes. We had numerous threads here and on r-package-devel (better list for the question IMHO, maybe follow-up there?) stating that new code really should avoid .C() and stick with .Call(). | On the R side, the returned SEXP will have class 'externalptr', with | not much to do about it programmatically. C code can additionally | register a finalizer on the object in order to release the memory | automatically after the it is discarded. (And Rcpp::XPtr sets those for you if you define RCPP_USE_FINALIZE_ON_EXIT.) A simpler approach is of course available too, and I used it too. Define your class as you would in C++. Then define - a helper function to initialize a class object via `new`, assign it to a static variable or a global pointer - helper functions for setters and getters of the values you need - a teardown function you can call, you may even tie it to R's on.exit() Now _you_ control lifetime and allocation. From R. If anything breaks, you get to keep the pieces. We can also help on the rcpp-devel list. Cheers, Dirk -- dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org