[Rcpp-devel] How to Get Pointer of Underlying Object of Rcpp Module Class

Tianqi Chen tianqi.tchen at gmail.com
Wed Oct 7 08:15:56 CEST 2015


Thanks to Wush Wu. I think I now find the answer to the question by
using RCPP_EXPOSED_CLASS_NODECL

One note is that I have to use Rcpp::internal::make_new_object to create
the S4 object, instead of Rcpp::wrap. Because current wrap do
copy-construct from an existing object to a new pointer.
While in my case, doing so will trigger the destructor of the class to free
the arrays, and a explicit copy is needed .

So what I did is return a  Rcpp::internal::make_new_object(new MyClass());
Which works for my case. But it sounds a bit undesirable as the function is
marked as internal.

Any suggestions?

Tianqi

On Tue, Oct 6, 2015 at 6:51 PM, Tianqi Chen <tianqi.tchen at gmail.com> wrote:

> Oh, the question is not about  supporting native Save/Load from R. I
> understand the hardness of that due to no customized loader from external
> pointer. The function listed here aims to write a customized function like
> ```save.list``` instead of R's native save/load, which is doable. The
> question is how to get the underlying external ptr from an Rcpp
> class_<MyClass> Object, within the life cycle of the R session. Sorry about
> the confusion.
>
>  Let me rephrase the question in this way: I want to implement a
> customized element-wise sum of a List of GPUArray object, which I exposed
> using Rcpp Module class. However, in order to do that, I need to somehow
> get the external Pointer of GPUArray from the S4 object, to redirect the
> call to InternalSumOnGPU function.
>
> After the computation, we need to wrap(construct) a new GPUArray S4 object
> from C++ side(what was normally provided was constructor from R side).
>
> ```
> class GPUArray {
> public:
>    static SEXP Sum(SEXP list) {
>           Rcpp::List data_lst(list);
>           std::vector<GPUArray *> internals(data_lst[i]);
>           for (size_t i = 0; i < data_lst.size(); ++i) {
>                SEXP obj = data_lst[i];
>                // Need to Get internal pointers from S4 GPUArray object
>                internals[i] = GetPtr<GPUArray>(obj);
>           }
>  GPUArray *ret = InternalSumOnGPU(internals);
>  // need to return the S4 object
>  return class_<GPUArray>(ret);
>    }
>
> };
>
> RCPP_MODULE(GPUArray) {
>      class_<GPUArray>("GPUArray");
>
>      function("gpu.sum", &GPUArray::Sum);
> }
> ```
>
>
> Tianqi
>
> On Tue, Oct 6, 2015 at 5:55 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
>
>>
>> On 6 October 2015 at 14:40, Tianqi Chen wrote:
>> | Dear Rcpp Developers:
>> |
>> | ```c++
>> | class MyClass {
>> | public:
>> |    static void SaveList(SEXP list, const std::string& filename) {
>> |           Rcpp::List data_lst(list);
>> |           std::vector<MyClass *> internals(data_lst[i]);
>> |           for (size_t i = 0; i < data_lst.size(); ++i) {
>> |                SEXP obj = data_lst[i];
>> |                // Need to Get internal pointers from S4 MyClass object
>> |                internals[i] = GetPtr<MyClass>(obj);
>> |           }
>> |           SomeRealSave(internals, filename);
>> |    }
>> |    static void LoadList(const std::string& filename) {
>> |           std::vector<MyClass > internals;
>> |           SomeReadLoad(&internals);
>> |           Rcpp::List out(internals.size());
>> |           for (size_t i = 0; i < internals.size(); ++i) {
>> |               // need to construct a MyClass object from C++ side
>> |               out[i] = MyClassConstructor(internals[i]);
>> |           }
>> |          return out;
>> |    }
>> | };
>> |
>> | RCPP_MODULE(MyClass) {
>> |      class_<MyClass>("MyClass");
>> |
>> |      function("save.myclass.list", &MyClass::SaveList);
>> |      function("load.myclass.list", &MyClass::LoadList);
>> | }
>> | ```
>> |
>> | To be specific, We have ways to Save/Load the pointers to the MyClass
>> object
>> | (in the SomeRealSave and SomeRealLoad). In our specific use-case, It
>> was an
>> | Array on GPU.
>>
>> As I recall, we had several discussions here a few years ago about the
>> impossibility of serialising Module objects to disk.  In short, you
>> can't. You write out a bunch of ram which you can re-read, but that
>> doesn't
>> make an object.
>>
>> You will have to rebuild the objects at the next run time so that memory
>> is
>> allocated and correctly pointed to.
>>
>> See here for one such prior email:
>>
>> http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2014-May/007539.html
>>
>> and an older one
>>
>> http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-April/002107.html
>>
>> | So the question is how is there any solution to  GetPtr<MyClass> and
>> | MyClassConstructor, so we can get the internal pointer of MyClass from
>> SEXP
>> | (which is the S4 object), and construct the corresponding S4 object
>> given the
>> | information of MyClass.
>> |
>> | What was wanted is indeed possible if we choose to only expose
>> XPtr<MyClass>,
>> | so we can simply do
>> | ```
>> |     MyClass * GetPtr<MyClass>(SEXP obj) {
>> |          XPtr<MyClass>(obj).get();
>> |     }
>> |     MyClassConstructor(MyClass *ptr) {
>> |         return XPtr<MyClass>(ptr);
>> |    }
>> |
>> | ```
>> |
>> | But it would be really nice we can directly return a wrapped S4 object
>> instead
>> | of raw ptr
>>
>> Yes, it would be -- but that doesn't meam it is possible under the current
>> framework.
>>
>> Sorry,  Dirk
>>
>> --
>> http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20151006/ab540a3d/attachment-0001.html>


More information about the Rcpp-devel mailing list