[Rcpp-devel] Pointer troubles

Romain Francois romain at r-enthusiasts.com
Wed Aug 3 15:58:40 CEST 2011


Hello,

Same as Dirk, I am not familiar with the OpenCL API. I can however give 
you some tips on external pointers to remove the need for some of the 
redundant code you would have to write when you directly use the R API 
for external pointers.

We have the Rcpp::XPtr template class that is parameterized by the class 
of the pointer, the XPtr object acts as a smart pointer, so can be 
passed down to whatever C++ function that needs a pointer. It also adds 
the necessary wrapping so that you can pass the object back to R as an 
external pointer.

With the XPtr class, you would write your code something like this:

SEXP getIntPointer(){
     int *test = new int; *test = 6;

     XPtr<int> retVal(test) ;
     return retVal ;
}

SEXP doubleIntPointer(SEXP test){
     XPtr<int> test2(test) ;
     return wrap( *test2 * 2 ) ;
}

You don't need intObjFinalizer because this is the same as the default 
finalizer that is shipped for free with XPtr:

template <typename T>
void standard_delete_finalizer(T* obj){
     delete obj ;
}

template <typename T, void Finalizer(T*) >
void finalizer_wrapper(SEXP p){
     if( TYPEOF(p) == EXTPTRSXP ){
	T* ptr = (T*) R_ExternalPtrAddr(p) ;
	Finalizer(ptr) ;
     }
}


You don't need int2SEXP because the XPtr constructor deals with it.

You don't need the SEXP2int because the XPtr dereferences itself to the 
actual underlying pointer class.

HTH,

Romain

Le 03/08/11 12:13, Willem Ligtenberg a écrit :
> Hi Dirk and list,
>
> Indeed it might have been a bit too complicated.
> I think I have another example, which explains my troubles without
> requiring OpenCL.
> In this case, I want to return a pointer to an integer value to R and
> the double the integer value in another function.
> (I know this is stupid to do, but it is a toy example)
>
> // Stuff to expose the int to R
> static void intObjFinalizer(SEXP ref){
>         if(TYPEOF(ref) == EXTPTRSXP){
>                 int *o = static_cast<int*>  (R_ExternalPtrAddr(ref));
>                 if (o) delete o;
>         }
> }
>
> SEXP int2EXP(int *o){
>         SEXP xp = R_MakeExternalPtr(o, R_NilValue, R_NilValue);
>         R_RegisterCFinalizerEx(xp, intObjFinalizer, TRUE);
>         return xp;
> }
>
> int *SEXP2int(SEXP o){
>         if(TYPEOF(o) != EXTPTRSXP)
>                 Rf_error("invalid object");
>         return (int*) R_ExternalPtrAddr(o);
> }
>
> SEXP getIntPointer(){
>      int test = 6;
>      SEXP retVal = int2EXP(&test);
>      std::cout<<  test<<  "\n";
>      int test2 = *SEXP2int(retVal);
>      std::cout<<  test2<<  "\n";
>      return retVal;
> }
>
> SEXP doubleIntPointer(SEXP test){
>      int test2 = *SEXP2int(test);
>      std::cout<<  test2;
>      return Rcpp::wrap(test2*2);
> }
>
> By the way, I use a module to expose these functions:
>
> RCPP_MODULE(ropencl){
> 	using namespace Rcpp ;
>      function( "getIntPointer"  ,&getIntPointer , "getIntPointer" ) ;
>      function( "doubleIntPointer"  ,&doubleIntPointer , "doubleIntPointer" ) ;
> }
>
> When I now execute getIntPointer() from R, it seems to work fine, both
> the initial integer and the value that I get back from
> *SEXP2int(retVal); are 6. (Although when I exit R after only this call
> I get the following: *** glibc detected *** /usr/lib64/R/bin/exec/R:
> free(): invalid pointer: 0x00007fffd1a587cc ***)
>
> However, when I now use doubleIntPointer(getIntPointer()) in R, I get
> some wrong result (a different value each time I restart R).
>
> Does this make it a bit more clear what I want to do, or the problems
> that I am facing?
>
> Kind regards,
>
> Willem
>
> On Tue, Aug 2, 2011 at 15:24, Dirk Eddelbuettel<edd at debian.org>  wrote:
>>
>> Hi Willem,
>>
>> Thanks a pretty long and complicated post.  Could we possibly break it down
>> into smaller pieces?
>>
>> On 2 August 2011 at 11:45, Willem Ligtenberg wrote:
>> | Hi,
>> |
>> | I am trying to wrap around OpenCL.
>> | But I am running into some problems when I try to return pointers to
>> | R. Later I want to be able to use these pointers in other c functions.
>> | As an example I have the following code:
>> |
>> | #include "createContext.h"
>> | #include<CL/opencl.h>
>> | #include<Rcpp.h>
>> |
>> | // Stuff to expose the cl_platform_id to R
>> | static void cl_platform_idObjFinalizer(SEXP ref){
>> |       if(TYPEOF(ref) == EXTPTRSXP){
>> |               cl_platform_id *o = static_cast<cl_platform_id*>  (R_ExternalPtrAddr(ref));
>> |               if (o) delete o;
>> |       }
>> | }
>> |
>> | SEXP cl_platform_id2EXP(cl_platform_id *o){
>> |       SEXP xp = R_MakeExternalPtr(o, R_NilValue, R_NilValue);
>> |       R_RegisterCFinalizerEx(xp, cl_platform_idObjFinalizer, TRUE);
>> |       return xp;
>> | }
>> |
>> | cl_platform_id *SEXP2cl_platform_id(SEXP o){
>> |       if(TYPEOF(o) != EXTPTRSXP)
>> |               Rf_error("invalid object");
>> |       return (cl_platform_id*) R_ExternalPtrAddr(o);
>> | }
>> |
>> | This bit I have found posted on this mailing list earlier.
>> | This is to expose a pointer to a cl_platform_id object in memory (and
>> | this should also take care of the clean up).
>> |
>> | Now I have the following method to get a list of platform_ids:
>> |
>> | SEXP getPlatformIDs(){
>> |       //returns a list of platform ids
>> |       cl_uint num_platforms = 0;
>> |       clGetPlatformIDs(0, 0,&num_platforms);
>> |       std::vector<cl_platform_id>  platforms(num_platforms);
>> |       clGetPlatformIDs(num_platforms, platforms.empty() ? NULL :
>> |&platforms.front(),&num_platforms);
>> |       //for each platform in platforms add its pointer to the return list
>> |       Rcpp::List result(platforms.size());
>> |       for (int i=0; i<platforms.size(); i++){
>> |         cl_platform_id tempPlatformID = platforms[i];
>> |               result[i] = cl_platform_id2EXP(&tempPlatformID);
>> |       }
>> |       return result;
>> | }
>> |
>> | And I want to get the name of the platform as follows:
>> |
>> | SEXP getPlatformName(SEXP sPlatformID){
>> |     char cBuffer[1024];
>> |     cl_platform_id platformID = *SEXP2cl_platform_id(sPlatformID);
>> |     clGetPlatformInfo (platformID, CL_PLATFORM_NAME, sizeof(cBuffer),
>> | cBuffer, NULL);
>> |     Rcpp::CharacterVector ab(1);
>> |     ab[0] = cBuffer;
>> |     return ab;
>>
>> You could use wrap() on std::string or char* if you just want to return a
>> single string. No need for a CharacterVector of size 1.
>>
>> | }
>> |
>> | The whole lot compiles, but gives a runtime error. When I try the
>> | following in R:
>> | library(ROpenCL)
>> | platformIDs<- getPlatformIDs()
>> | print(getPlatformName(platformIDs[[1]]))
>> |
>> | *** caught segfault ***
>> | address 0x51, cause 'memory not mapped'
>> |
>> | Now when I put all this together in one method which just returns the
>> | platform name, it works:
>> |
>> | SEXP getPlatformIDs2(){
>> |       //returns a list of platform ids
>> |       cl_uint num_platforms = 0;
>> |       clGetPlatformIDs(0, 0,&num_platforms);
>> |       std::vector<cl_platform_id>  platforms(num_platforms);
>> |       clGetPlatformIDs(num_platforms, platforms.empty() ? NULL :
>> |&platforms.front(),&num_platforms);
>> |       char cBuffer[1024];
>> |     clGetPlatformInfo (platforms[0], CL_PLATFORM_NAME,
>> | sizeof(cBuffer), cBuffer, NULL);
>> |     Rcpp::CharacterVector ab(1);
>> |     ab[0] = cBuffer;
>> |     return ab;
>> | }
>> |
>> | This results in:
>> | getPlatformIDs2()
>> | [1] "NVIDIA CUDA"
>> |
>> | Could someone check if I am taking the pointer to and from R in the correct way?
>>
>> I can't as I do not know the OpenCL API.
>>
>> One thought is that maybe you do not you really need external pointers as you
>> are just copying IDs around. Can you simplify what you are trying to do?
>>
>> Cheers, Dirk
>>
>> --
>> Gauss once played himself in a zero-sum game and won $50.
>>                       -- #11 at http://www.gaussfacts.com
>>
> _______________________________________________
> 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
>


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
http://romain-francois.com
|- http://bit.ly/lJoWbH : Montpellier Comédie Club - Juin 2011
|- http://bit.ly/kaSV6U : Stand up set at Up The Creek
`- http://bit.ly/hdKhCy : Rcpp article in JSS




More information about the Rcpp-devel mailing list