[Rd] SEXP and slots

Romain Francois romain at r-enthusiasts.com
Mon Nov 15 21:15:03 CET 2010


Hello,

Since people have whisperred about Rcpp, I'd like to play too.

> On 11/15/2010 07:45 AM, Patrick Leyshock wrote:
>> Very helpful, thank you.
>>
>> A couple other questions, please:
>>
>> 1.  I've got a function written in C, named "my_c_function".  In my R
>> code I call this function, passing to it an INTSXP and a STRSXP,
>> respectively:
>>
>>    result <- .Call("my_c_function", int_vector, str_vector)
>>
>> The prototype of "my_c_function" is:
>>
>>    SEXP my_c_function(SEXP int_vec, SEXP str_vec);
>>
>> Within my_c_function I am able to extract the values within the integer
>> vector, e.g. I can grab the first value with these lines of code:
>>
>>    int extracted_value;
>>    extracted_value = *INTEGER(int_vec);
>>
>> What I cannot figure out how to do is extract the value from the
>> STRSXP.  I'm assuming that I can create a pointer to a character array,
>> then malloc enough memory to hold the value.  Is there an analogous
>> operation on "INTEGER" for STRSXPs?
>
> STRING_ELT(str_vec, 0)
>
> gets the 0th component of str_vec, which is a CHARSXP, i.e., an SEXP for
> a character string. The char* can be retrieved with CHAR, so the usual
> paradigm is
>
>   const char *x = CHAR(STRING_ELT(str_vec, 0));
>
> note the const-ness of the char* -- it's not mutable, because R is
> managing char * memory.
>
> The converse action, of assigning to an element, is
>
>   SET_STRING_ELT(str_vec, 0, mkChar("foo"));
>
> mkChar() is creating a copy (if necessary) of "foo", managing it, and
> returning a CHARSXP. Working through protection (which will likely be
> your next obstacle ;) in this last example is a good exercise.

In Rcpp, you would wrap up the STRSXP into a CharacterVector and then 
pull things in and out using indexing:

Rcpp::CharacterVector aladdin(str_vec) ;
std::string first = aladdin[0] ;
aladdin[0] = "foobar" ;

> There is a parallel operation VECTOR_ELT / SET_VECTOR_ELT for lists.

Same thing for lists:

Rcpp::List yasmine( some_vec_sxp ) ;
double x = yasmine[0] ;
yasmine[0] = "bla" ;

>> 2.  Any good references/resources for developing R?  Nearly all the
>> documents I've found are for programming R as a user, not as a
>> developer.  I have copies of the documentation, which are very helpful,
>> but it'd be helpful to have additional resources to fill in their gaps.
>
> Chambers, 2008, Software for Data Analysis: Programming with R chapters
> 11 & 12,
>
> Gentleman, 2008, R Programming for Bioinformatics chapter 6
>
> might be helpful, but by the time they arrive you might find that you're
> most of the way through the material covered...
>
> I guess my opinion is that Rcpp would not be useful for understanding
> R's C layer, whatever its merits for 'getting the job done'.

Right, but we try to put a positive spin on this.

Rcpp hides the C API on purpose, so that users can concentrate on 
solving their problem rather than deal/fight with the C API.



Back to the original question, Rcpp also has (although it is less used) 
an Rcpp::S4 class that can be used to deal with slots. Here is a 
complete example using Rcpp and inline:

require( Rcpp)
require( inline )

setClass("example",
    representation  (
           size = "numeric",
           id    = "character"
    )
)

fx <- cxxfunction( signature(x = "example"),
'
     S4 obj(x) ;
     obj.slot( "size" ) = 10 ;
     obj.slot( "id"   ) = "foo" ;
     return obj ;
', plugin = "Rcpp" )

str( fx( new("example", size=4, id="id_value") ) )

But as Martin says, it all depends on what your goal is: getting the job 
done or learn about the internal C API.

Romain


> Martin
>
>>
>> Thank you,
>>
>> Patrick
>>
>>
>> On Fri, Nov 12, 2010 at 4:36 PM, Martin Morgan <mtmorgan <at> fhcrc.org
>> <mailto:mtmorgan <at> fhcrc.org>> wrote:
>>
>>     On 11/12/2010 02:31 PM, Patrick Leyshock wrote:
>>     > Hello,
>>     >
>>     > I've created this class:
>>     >
>>     > setClass("example",
>>     >    representation  (
>>     >           size = "numeric",
>>     >           id    = "character"
>>     >    )
>>     > )
>>     >
>>     > Suppose I create a new instance of this class:
>>     >
>>     >> x <- new("example", 4, "id_value")
>>     >
>>     > This creates an S4 object with two slots.  Am I correct in
>>     thinking that
>>     > slots are "filled" by SEXPs?
>>
>>     Hi Patrick --
>>
>>     If I
>>
>>     > eg = new("example", size=4, id="id_value")
>>
>>     (note the named arguments) and take a peak at the str'ucture of eg,
>>     I see
>>
>>     > str(eg)
>>     Formal class 'example' [package ".GlobalEnv"] with 2 slots
>>      ..@ size: num 4
>>      ..@ id  : chr "id_value"
>>
>>     so the @size slot is a numeric vector of length 1 containing the value
>>     4. One doesn't really have to know the detailed representation, but one
>>     can find out from
>>
>>     > .Internal(inspect(eg))
>>     @df70e48 25 S4SXP g0c0 [OBJ,NAM(2),gp=0x10,ATT]
>>     ATTRIB:
>>      @df70ef0 02 LISTSXP g0c0 []
>>        TAG: @769258 01 SYMSXP g1c0 [MARK] "size"
>>        @c0f6db8 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 4
>>        TAG: @15b0228 01 SYMSXP g1c0 [MARK,NAM(2)] "id"
>>        @c0f6178 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0)
>>          @12341c80 09 CHARSXP g0c2 [gp=0x20] "id_value"
>>        TAG: @607ce8 01 SYMSXP g1c0 [MARK,NAM(2),gp=0x4000] "class"
>>        @c0f6d58 16 STRSXP g0c1 [NAM(2),ATT] (len=1, tl=0)
>>          @96ed08 09 CHARSXP g1c1 [MARK,gp=0x21] "example"
>>        ATTRIB:
>>          @df70fd0 02 LISTSXP g0c0 []
>>            TAG: @624f70 01 SYMSXP g1c0 [MARK,NAM(2)] "package"
>>            @c0f6d88 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0)
>>              @67f5e0 09 CHARSXP g1c2 [MARK,gp=0x21,ATT] ".GlobalEnv"
>>
>>     that the 'eg' object is an S4SXP with an attribute that is a LISTSXP.
>>     The LISTSXP has elements that are tagged with SYMSXP representing the
>>     slot name, and values that are REALSXP (for 'size') or STRSXP (for
>>     'id'). The LISTSXP attribute itself has an attribute, which contains
>>     information about the package where the class is defined. With these
>>     hints one can see through the S4 interface to the underlying
>>     implementation
>>
>>     > attributes(eg)
>>     $size
>>     [1] 4
>>
>>     $id
>>     [1] "id_value"
>>
>>     $class
>>     [1] "example"
>>     attr(,"package")
>>     [1] ".GlobalEnv"
>>
>>     But probably you have a specific goal in mind, and this is too much
>>     information...
>>
>>     Martin
>>
>>     >
>>     > Thanks, Patrick
>>     >
>>     >       [[alternative HTML version deleted]]
>>     >
>>     > ______________________________________________
>>     > R-devel <at> r-project.org <mailto:R-devel <at> r-project.org> mailing list
>>     > https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>>     --
>>     Computational Biology
>>     Fred Hutchinson Cancer Research Center
>>     1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109
>>
>>     Location: M1-B861
>>     Telephone: 206 667-2793
>>
>>
>
> --
> Computational Biology
> Fred Hutchinson Cancer Research Center
> 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109
>
> Location: M1-B861
> Telephone: 206 667-2793


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/9VOd3l : ZAT! 2010
|- http://bit.ly/c6DzuX : Impressionnism with R
`- http://bit.ly/czHPM7 : Rcpp Google tech talk on youtube



More information about the R-devel mailing list