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
[Rcpp-devel] Pointer troubles
12 messages · Dirk Eddelbuettel, Willem Ligtenberg, Steve Lianoglou +2 more
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
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,
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
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
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
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
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:
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
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 :
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,
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
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
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
Gauss once played himself in a zero-sum game and won $50.
-- #11 at http://www.gaussfacts.com
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:
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.
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
Steve Lianoglou Graduate Student: Computational Systems Biology ?| Memorial Sloan-Kettering Cancer Center ?| Weill Medical College of Cornell University Contact Info: http://cbio.mskcc.org/~lianos/contact
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<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
-- 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 at 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
Le 3 ao?t 2011 ? 17:13, Sebastian Weber <sebastian.weber at frias.uni-freiburg.de> a ?crit :
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?
Yes
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.
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.
Moreover, I saw that basically the whole class_-declaration mechanism boils down to stuff things into XPtr, right?
Yep
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...
Not sure yet. I'll mess around and see if i can get a toy example going. Romain
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<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
-- 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 at 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