Re: [Rd] SEXP and slots

From: Romain Francois <romain_at_r-enthusiasts.com>
Date: Mon, 15 Nov 2010 21:15:03 +0100


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

______________________________________________
R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Received on Mon 15 Nov 2010 - 20:22:17 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Tue 16 Nov 2010 - 13:10:21 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive