[Rcpp-devel] USE_RINTERNALS and Rcpp

Romain Francois romain at r-enthusiasts.com
Mon Sep 23 18:43:22 CEST 2013


Le 23/09/13 18:24, Hadley Wickham a écrit :
> Thanks!
>
> There's no way to make this less fragile (i.e. by using Defn.h),
> right? (Because Defn.h isn't "exported" by R)
>
> Hadley

I'm afraid you're right. Defn.h is not part of the distributed files.

Now you might be able to negociate that some of these are promoted to 
public api in a future version, but I would not put my money on it.


And for these:

extern void UNIMPLEMENTED_TYPE(const char *s, SEXP x) ;
extern SEXP csduplicated(SEXP) ;


R makes it difficult for you to use that sort of trick.

I've updated the gist with what happens if you put the code in a 
package: https://gist.github.com/romainfrancois/6672944

You get that note:

* checking compiled code ... NOTE
File ‘/private/tmp/foo.Rcheck/foo/libs/foo.so’:
   Found non-API calls to R: ‘UNIMPLEMENTED_TYPE’, ‘csduplicated’

Romain

> On Mon, Sep 23, 2013 at 11:17 AM, Romain Francois
> <romain at r-enthusiasts.com> wrote:
>> Hi,
>>
>> I would not do that kind of internal things with Rcpp. Instead put code from
>> this gist https://gist.github.com/romainfrancois/6672944 on a .c file and go
>> old school about it:
>>
>> $ R CMD SHLIB size.c
>> $ Rscript -e "dyn.load('size.so'); siz <- function(.) .Call( 'siz', .) ;
>> siz(1:10); siz(siz); siz(letters) "
>> [1] 88
>> [1] 600
>> [1] 1496
>>
>> Romain
>>
>> Le 23/09/13 17:45, Hadley Wickham a écrit :
>>
>>> Hi all,
>>>
>>> Is it possible to access the R internals api through Rcpp?  For
>>> example, I want to right my own version of object.size() that's aimed
>>> at detecting memory leaks, so it needs to recursively include the size
>>> of environments. The objectsize C function needs to access R internals
>>> to get the size of various vectors (BYTE2VEC, INT2VEC etc) - is there
>>> a way to accomplish the same thing through Rcpp? (Source code for
>>> objectsize included below)
>>>
>>> Thanks!
>>>
>>> Hadley
>>>
>>>
>>> static R_size_t objectsize(SEXP s)
>>> {
>>>       R_size_t cnt = 0, vcnt = 0;
>>>       SEXP tmp, dup;
>>>       Rboolean isVec = FALSE;
>>>
>>>       switch (TYPEOF(s)) {
>>>       case NILSXP:
>>>           return(0);
>>>           break;
>>>       case SYMSXP:
>>>           break;
>>>       case LISTSXP:
>>>       case LANGSXP:
>>>       case BCODESXP:
>>>           cnt += objectsize(TAG(s));
>>>           cnt += objectsize(CAR(s));
>>>           cnt += objectsize(CDR(s));
>>>           break;
>>>       case CLOSXP:
>>>           cnt += objectsize(FORMALS(s));
>>>           cnt += objectsize(BODY(s));
>>>           /* no charge for the environment */
>>>           break;
>>>       case ENVSXP:
>>>       case PROMSXP:
>>>       case SPECIALSXP:
>>>       case BUILTINSXP:
>>>           break;
>>>       case CHARSXP:
>>>           vcnt = BYTE2VEC(length(s)+1);
>>>           isVec = TRUE;
>>>           break;
>>>       case LGLSXP:
>>>       case INTSXP:
>>>           vcnt = INT2VEC(xlength(s));
>>>           isVec = TRUE;
>>>           break;
>>>       case REALSXP:
>>>           vcnt = FLOAT2VEC(xlength(s));
>>>           isVec = TRUE;
>>>           break;
>>>       case CPLXSXP:
>>>           vcnt = COMPLEX2VEC(xlength(s));
>>>           isVec = TRUE;
>>>           break;
>>>       case STRSXP:
>>>           vcnt = PTR2VEC(xlength(s));
>>>           dup = csduplicated(s);
>>>           for (R_xlen_t i = 0; i < xlength(s); i++) {
>>>               tmp = STRING_ELT(s, i);
>>>               if(tmp != NA_STRING && !LOGICAL(dup)[i])
>>>                   cnt += objectsize(tmp);
>>>           }
>>>           isVec = TRUE;
>>>           break;
>>>       case DOTSXP:
>>>       case ANYSXP:
>>>           /* we don't know about these */
>>>           break;
>>>       case VECSXP:
>>>       case EXPRSXP:
>>>       case WEAKREFSXP:
>>>           /* Generic Vector Objects */
>>>           vcnt = PTR2VEC(xlength(s));
>>>           for (R_xlen_t i = 0; i < xlength(s); i++)
>>>               cnt += objectsize(VECTOR_ELT(s, i));
>>>           isVec = TRUE;
>>>           break;
>>>       case EXTPTRSXP:
>>>           cnt += sizeof(void *);  /* the actual pointer */
>>>           cnt += objectsize(EXTPTR_PROT(s));
>>>           cnt += objectsize(EXTPTR_TAG(s));
>>>           break;
>>>       case RAWSXP:
>>>           vcnt = BYTE2VEC(xlength(s));
>>>           isVec = TRUE;
>>>           break;
>>>       case S4SXP:
>>>           /* Has TAG and ATRIB but no CAR nor CDR */
>>>           cnt += objectsize(TAG(s));
>>>           break;
>>>       default:
>>>           UNIMPLEMENTED_TYPE("object.size", s);
>>>       }
>>>       /* add in node space:
>>>          we need to take into account the rounding up that goes on
>>>          in the node classes. */
>>>       if(isVec) {
>>>           cnt += sizeof(SEXPREC_ALIGN);
>>>           if (vcnt > 16) cnt += 8*vcnt;
>>>           else if (vcnt > 8) cnt += 128;
>>>           else if (vcnt > 6) cnt += 64;
>>>           else if (vcnt > 4) cnt += 48;
>>>           else if (vcnt > 2) cnt += 32;
>>>           else if (vcnt > 1) cnt += 16;
>>>           else if (vcnt > 0) cnt += 8;
>>>       } else cnt += sizeof(SEXPREC);
>>>       /* add in attributes: these are fake for CHARSXPs */
>>>       if(TYPEOF(s) != CHARSXP) cnt += objectsize(ATTRIB(s));
>>>       return(cnt);
>>> }


-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30



More information about the Rcpp-devel mailing list