[Rcpp-devel] Pointer troubles

Dirk Eddelbuettel edd at debian.org
Tue Aug 2 15:24:28 CEST 2011


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