Hi! Reading this thread, I hit on some questions which would help me understand Rcpp a lot better.
> 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. Hmm, I understand that XPtr is always a "strong" pointer in the sense that XPtr will delete the object once it gets out of scope. Is that right? If so, how can I get a weak pointer? I.e. tell XPtr to never call a finalizer at all since the ownership is handled at a different spot in my code. Moreover, I saw that basically the whole class_-declaration mechanism boils down to stuff things into XPtr, right? So on the C++ side one has actually pointers to wrapped classes which are held by XPtr. How can I now obtain these pointers and what is the type of the wrapped classes? The problem is that I have to deal with a wrapped class A, but might also fool around with A* in my code... Cheers, Sebastian > > 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<e...@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@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 > > > _______________________________________________ > Rcpp-devel mailing list > Rcpp-devel@lists.r-forge.r-project.org > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel -- Sebastian Weber Group of Cell Communication and Control Freiburg Institute for Advanced Studies - FRIAS School of Life Sciences - LIFENET Albert-Ludwigs-Universität Freiburg Albertstr. 19 79104 Freiburg T.: +49-761-203-97237 Fax:+49-761-203-97334 _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel