[Rcpp-devel] Pointer troubles

Willem Ligtenberg willem.ligtenberg at openanalytics.eu
Wed Aug 3 12:13:05 CEST 2011


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
>


More information about the Rcpp-devel mailing list