Message-ID: <CAK0yx2emLVnZspxTgpZCFg+fhQEo5ETjTU81ftK0Pvdhb-=WyA@mail.gmail.com>
Date: 2011-08-03T12:18:14Z
From: Willem Ligtenberg
Subject: [Rcpp-devel] Pointer troubles
In-Reply-To: <20025.14637.214993.226169@max.nulle.part>
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;
*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
>