[Rcpp-devel] Pointer troubles

Dirk Eddelbuettel edd at debian.org
Wed Aug 3 15:33:27 CEST 2011


On 3 August 2011 at 14:18, Willem Ligtenberg wrote:
| Hi Dirk (and list),
| 
| Yes, the above does help.
| Although, I actually got the toy example to work about 5 minutes ago. :)
| And just 1 minute ago also the OpenCL method. :D
| At this moment I am a very happy person!
| 
| And for future reference I change the methods into this:
| SEXP getIntPointer(){
|     int *test = new int;

Please keep all the warning in the 'Writing R Extensions' about not to mix
new/delete and the R allocations.

Also, this looks like a resource leak, no?  test never gets freed.

That said, as a proof of concept for wrapping an int pointer, it is probably
good enough.

Dirk

|     *test = 6;
|     SEXP retVal = int2EXP(test);
|     int test2 = *SEXP2int(retVal);
|     return retVal;
| }
| 
| SEXP doubleIntPointer(SEXP test){
|     int test2 = *SEXP2int(test);
|     return Rcpp::wrap(test2*2);
| }
| 
| Kind regards,
| 
| Willem
| 
| On Wed, Aug 3, 2011 at 14:03, Dirk Eddelbuettel <edd at debian.org> wrote:
| >
| > Hi Willem,
| >
| > On 3 August 2011 at 12:13, Willem Ligtenberg wrote:
| > | 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)
| >
| > Toy examples are good.
| >
| > | // 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);
| >
| > Isn't &test now the address of a temp object in the function getIntPointer ?
| > That memory space doesn't persist after the call.
| >
| > Maybe you should take the address of a global (static) variable, or allocate
| > memory.
| >
| > |     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?
| >
| > Does the above help?
| >
| > Cheers, Dirk
| >
| > | 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
| >
| > --
| > 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

-- 
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