[Rd] Calling an array in a struct in C to R
Romain Francois
romain at r-enthusiasts.com
Thu Jun 20 14:36:57 CEST 2013
Hello,
I would use external pointers for something like this.
If c++ is an option, you can take advantage of Rcpp classes to deal with
external pointers. Put the following in a .cpp and sourceCpp() it.
#include <Rcpp.h>
using namespace Rcpp ;
class Array {
public:
Array( ) : size(10), used(0){
array = new float[10] ;
}
~Array(){
delete[] array ;
}
size_t get_used(){ return used ; }
// other methods doing stuff with the data
private:
float *array;
size_t used;
size_t size;
} ;
typedef XPtr<Array> ArrayPointer ;
// [[Rcpp::export]]
ArrayPointer create_ptr( ){
return ArrayPointer( new Array ) ;
}
// [[Rcpp::export]]
size_t Array_get_used(ArrayPointer obj){
// here we use ArrayPointer just like an Array*
return obj->get_used() ;
}
Now, this is very raw and at the R level you get opaque external pointers:
> a <- create_ptr()
> str(a)
<externalptr>
> Array_get_used(a)
[1] 0
You can go further than this and use Rcpp modules so that you don't need
to worry about external pointers, which you can consider as
implementation details. For example:
#include <Rcpp.h>
using namespace Rcpp ;
class Array {
public:
Array( ) : size(10), used(0){
array = new float[10] ;
}
~Array(){
delete[] array ;
}
size_t get_used(){ return used ; }
// other methods doing stuff with the data
private:
float *array;
size_t used;
size_t size;
} ;
// the module code, this is where you declare what of
// your class you expose to the R level
RCPP_MODULE(ArrayModule){
class_<Array>("Array")
.constructor()
.method( "get_used", &Array::get_used)
;
}
With this, the R code looks like this:
# we should get rid of the need to call populate.
# for now let us just assume it is a way to copy
# the content of the module
# into the global environment
> populate(ArrayModule, globalenv())
> b <- new(Array)
> str(b)
Reference class 'Rcpp_Array' [package ".GlobalEnv"] with 0 fields
list()
and 15 methods, of which 3 are possibly relevant:
finalize, get_used, initialize
> b$get_used()
[1] 0
Romain
Le 19/06/13 16:14, Tee-Jay-Ardie a écrit :
> Hi there,
>
> Although I'm a quite experienced R user and know my ways in C, I stumbled
> upon a problem I don't know how to solve. Therefore, I hope someone can
> provide me with the information or pointers I need in order to understand
> the way in which the communication between R and C occurs. I have the
> following C code which basicallly reflects what I want:
>
> typedef struct
> {
> float *array;
> size_t used;
> size_t size;
> } Array;
>
> void main2R()
> {
> Array a;
> examplefunction(&a); /*fills and dynamically grows a->array*/
> }
>
> Now I would want to return a.array or a->array to R. According to the R
> manuals, the compiled C code should not return anything except through its
> arguments. The problem here is, I have a dynamically growing array, and I
> have no idea what to pass on to C from R in order to let that work.
> The word 'should' indicates that the compiled code may return something in
> special circumstances, but I have no idea how to get a.array in R.
>
> So my question is simply this: How on earth do I get the information in the
> float array 'a.array' in R? Is it even possible or should I rewrite my C
> code using Call in R?
>
> Another, not preferred, options is to pre-allocate the array/vector in R on
> a fixed (large-enough) size? Or do I miss something here?
>
> Regards.
--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
R Graph Gallery: http://gallery.r-enthusiasts.com
blog: http://blog.r-enthusiasts.com
|- http://bit.ly/13SrjxO : highlight 0.4.2
`- http://bit.ly/10X94UM : Mobile version of the graph gallery
More information about the R-devel
mailing list