Skip to content

[Rcpp-devel] Pointer troubles

12 messages · Dirk Eddelbuettel, Willem Ligtenberg, Steve Lianoglou +2 more

#
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;
}

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?
Thanks in advance,

Willem Ligtenberg
#
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
#
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,
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
#
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:
#
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
#
Hi Dirk,

Won't test be cleared up when the garbage collector calls
intObjFinalizer(PointerTotest)? That is what I thought the finalizer
would do.
Is there a specific chapter about the mixing of new/delete and the R
allocations?

Kind regards,

Willem
On Wed, Aug 3, 2011 at 15:33, Dirk Eddelbuettel <edd at debian.org> wrote:
#
Hello,

Same as Dirk, I am not familiar with the OpenCL API. I can however give 
you some tips on external pointers to remove the need for some of the 
redundant code you would have to write when you directly use the R API 
for external pointers.

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.

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 :

  
    
#
On 3 August 2011 at 15:44, Willem Ligtenberg wrote:
| Hi Dirk,
| 
| Won't test be cleared up when the garbage collector calls
| intObjFinalizer(PointerTotest)? That is what I thought the finalizer
| would do.
| Is there a specific chapter about the mixing of new/delete and the R
| allocations?

It may have been in Section 6.1 about 'Memory allocation' but I don't see it
right now.  I may have misremembered the recommendation about new/delete with
the one for malloc/free: most of the time you are better off using the R
facilities as you fall back onto R's error handling.

And in general, you should not need new / delete. Modern C++ uses STL
containers which hide all this, and Rcpp conveniently wraps that for you --
just like Romain just showed you the simpler XPtr use.

Dirk
#
Hi Romain (and all),

Just one question about a point you made ... from my previous postings
on the list, we now by know that I'm no c++ expert, so ... sorry if
this is a dumb question.

I use XPtr often in my current Rcpp endeavor to wrap an external c++
lib, and when you say:
I think I've run into peculiars in the library I'm wrapping that
suggests otherwise.

The library I'm wrapping has a macro defined that you pass points to
object into to handle some basic reference counting/gc it has
implemented.

Part of the macro checks to see if there are any other objects
"holding on to" the pointer to the object that was sent in, and if not
it sets the pointer to NULL. A brief approximation of this macro looks
like so:

UNREF(x) {
  if (x) {
    if ((x)->unref()==0) {
      (x)=NULL;
    }
  }
}

The assignment of x to NULL trips up when I pass an XPtr down into
this function.

I've gotten around this by just not passing an XPtr down to this part
of the code, so it's no big deal, but is this the one example where
the XPtr can't be passed around another c++ library as ...
"promiscuously" (for lack of a better word) ... as we would hope?

Just thought I'd but that out there since this just popped up.

Thanks,
-steve
#
Hi!

Reading this thread, I hit on some questions which would help me understand Rcpp a lot better.
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

  
    
#
Le 3 ao?t 2011 ? 17:13, Sebastian Weber <sebastian.weber at frias.uni-freiburg.de> a ?crit :
Yes
You can register your own finalizer, that does whatever you want, release ressources, etc ...

This is handled by a second template parameter of the XPtr template. 

This was added recently and i sent an email to the list, one month or so ago.
Yep
Not sure yet. I'll mess around and see if i can get a toy example going. 

Romain