如何获得SEXPTYPE的SEXP值?

时间:2014-08-07 00:28:05

标签: c++ rcpp

假设我有一个以SEXP类型为参数的函数:

SEXP myFun(SEXP param)

如何找出此参数的类型?查看调试器中的SEXP类型,我可以看到我可以调用param->sxpinfo.type来获取SEXPTYPE的数字表示。从快速浏览一下,它们似乎与这些匹配:

no    SEXPTYPE    Description 
0 NILSXP  NULL 
1 SYMSXP  symbols 
2 LISTSXP pairlists 
3 CLOSXP  closures 
4 ENVSXP  environments 
5 PROMSXP promises 
6 LANGSXP language objects 
7 SPECIALSXP  special functions 
8 BUILTINSXP  builtin functions 
9 CHARSXP internal character strings 
10    LGLSXP  logical vectors 
13    INTSXP  integer vectors 
14    REALSXP numeric vectors 
15    CPLXSXP complex vectors 
16    STRSXP  character vectors 
17    DOTSXP  dot-dot-dot object 
18    ANYSXP  make “any” args work 
19    VECSXP  list (generic vector) 
20    EXPRSXP expression vector 
21    BCODESXP    byte code 
22    EXTPTRSXP   external pointer 
23    WEAKREFSXP  weak reference 
24    RAWSXP  raw vector 
25    S4SXP   S4 classes not of simple type

(来源:http://www.biosino.org/R/R-doc/R-ints/SEXPTYPEs.html#SEXPTYPEs

但这看起来很糟糕。检查SEXP变量类型的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

使用R API,TYPEOF宏用于获取运行时类型。我们可以看到来自Rinternals.h的一些相关位(有趣的是,不是编码为enum,而是作为一系列宏定义;假设是为了向后兼容一些非常糟糕的编译器一些非常糟糕的平台...)

typedef unsigned int SEXPTYPE;

#define NILSXP       0    /* nil = NULL */
#define SYMSXP       1    /* symbols */
#define LISTSXP      2    /* lists of dotted pairs */
#define CLOSXP       3    /* closures */
#define ENVSXP       4    /* environments */
#define PROMSXP      5    /* promises: [un]evaluated closure arguments */
#define LANGSXP      6    /* language constructs (special lists) */
#define SPECIALSXP   7    /* special forms */
#define BUILTINSXP   8    /* builtin non-special forms */
#define CHARSXP      9    /* "scalar" string type (internal only)*/
#define LGLSXP      10    /* logical vectors */
/* 11 and 12 were factors and ordered factors in the 1990s */
#define INTSXP      13    /* integer vectors */
#define REALSXP     14    /* real variables */
#define CPLXSXP     15    /* complex variables */
#define STRSXP      16    /* string vectors */
#define DOTSXP      17    /* dot-dot-dot object */
#define ANYSXP      18    /* make "any" args work.
                 Used in specifying types for symbol
                 registration to mean anything is okay  */
#define VECSXP      19    /* generic vectors */
#define EXPRSXP     20    /* expressions vectors */
#define BCODESXP    21    /* byte code */
#define EXTPTRSXP   22    /* external pointer */
#define WEAKREFSXP  23    /* weak reference */
#define RAWSXP      24    /* raw bytes */
#define S4SXP       25    /* S4, non-vector */

/* used for detecting PROTECT issues in memory.c */
#define NEWSXP      30    /* fresh node creaed in new page */
#define FREESXP     31    /* node released by GC */

#define FUNSXP      99    /* Closure or Builtin or Special */

如果定义了USE_RINTERNALS,我们可以看到R在SEXPTYPE中查询:

#define TYPEOF(x)   ((x)->sxpinfo.type)

这正如你所说的那样:)但在大多数情况下(即 - 除非你知道你正在做什么),你不应该使用#define,所以定义来自memory.c

int (TYPEOF)(SEXP x) { return TYPEOF(CHK(x)); }

...只是调用TYPEOF宏,但使用CHK来确保SEXP它已经不受保护{\ n}}

浏览R源(并且一定要查看R.hRinternals.h)以了解R API中实际暴露的内容及其使用方式非常有用

也就是说,R API是一个丑陋的野兽,所以我们确实建议使用Rcpp,它提供了许多很好的类,它们包裹SEXP但提供编译时类型和一系列有用的函数来使用/操作它们。请参阅@ eddelbuettel' s Rcpp page作为介绍,the Rcpp Gallery例如使用Rcpp。