[Rd] Heap access across multiple calls from R to C++

pik@pp@@devei m@iii@g oii gm@ii@com pik@pp@@devei m@iii@g oii gm@ii@com
Wed May 24 02:08:25 CEST 2023


Dear all,

 

I have a question about maintaining state in native code during the lifetime
of an object of R6Class type. The background is the following. I have a
class derived from the standard model class of the R port of Keras, and I
want to perform some calculations in native code using a third-party
library. I am working with R's C interface. To avoid memory initializations
and some indexing calculations during the model's training, I want to
initialize a native structure on the heap during the construction of the
R6Class, prepare everything, and use this structure later to perform the
calculations on the native side. As you can see, this requires maintaining
the state during successive calls to my native code, and because of the
third-party software I am relying on, I do not see an efficient way to
organize my code differently.

 

I think I have a working way of doing what I intend, but I am skeptical
about its portability, and I would like to get some feedback or ideas for a
better implementation. So, a minimalistic description of my approach goes
along the following line (not tested example snippet):

 

In R:

R6::R6Class("my_model", public = list(

  native_obj = double(1),

  initialize = function() {

    .C("make_native_obj", self$native_obj)

  }), private = list (

  finalize = function() {

    .C("release_native_obj", self$native_obj)

  }))

 

In C(++):

extern "C" void make_native_obj(double *obj) {

  auto native_obj = new NativeObjStruct();

  memcpy(obj, &native_obj, sizeof(obj));  

}

extern "C" void release_native_obj(double *obj) {

  NativeObjStruct *native_obj{nullptr};

  memcpy(&native_obj, obj, sizeof(native_obj));  

   delete native_obj ;

}

 

This assumes that sizeof(double)=8=sizeof(native_obj*) and works on my
machine with g++, clang, and msvc. Although I have never personally used a
setup in which this condition is false, I wonder if it is universal in all
the platforms relevant to R.

 

Is there a better way to do this? From the C++ side, uintptr_t would be
cleaner, but if I am not mistaken, I would then need integer(2) on the R
side. Would this be better? Is there maybe a more standard way that this
problem is solved in other cases? I have searched the R internals page, but
I could not find something to help me. Essentially, I am asking for an
approach corresponding to PyCapsule of the Python C API. I am looking for
alternatives, preferably as lightweight as possible and, at least portable
to the CRAN platforms.

 

I would be very thankful for any suggestions or tips! 

 

Kind Regards,

Pantelis

 


	[[alternative HTML version deleted]]



More information about the R-devel mailing list