如何在Rcpp中确定存储在SEXP中的对象的class?

How to determine the class of object stored in SEXP in Rcpp?

//[[Rcpp::export]]
int Class_data(SEXP data) {
    /*
       return 0 if class of data is matrix
       else return -1 
    */
}

如何确定上述情况下data的class?如果 data 属于 matrix class return 0 否则 return -1.

通常,在使用 Rcpp 时,您会事先知道对象的类型,因为您会指定:

//[[Rcpp::export]]
int Class_data(Rcpp::NumericMatrix) {
  // code to reduce return to int
  return 1;
}

当然,当使用不同的元素类型(例如逻辑、字符和数字)并且具有一个调用函数时,也有例外。我在最后包含了一个这样的例子。

不过,如果你不这样做,最好的办法是在 R 的词汇表中使用 isMatrix

INLINE_FUN Rboolean isMatrix(SEXP s)
{
    SEXP t;
    if (isVector(s)) {
    t = getAttrib(s, R_DimSymbol);
    /* You are not supposed to be able to assign a non-integer dim,
       although this might be possible by misuse of ATTRIB. */
    if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
        return TRUE;
    }
    return FALSE;
}

Implementation

要处理大量对象(逻辑、字符等),您需要 R 中给出的内部开关 do_is() function

虽然这可能有点太大,但您可能需要帮助来分派不同的对象类型。为此,请参阅此示例:

#include <Rcpp.h>

// Create a template generic (look up C++ templates)
template <int RTYPE>
int count_me(Vector<RTYPE> v){
    return v.size() ; // Just want to show it can return sizes of different array types
}

// [[Rcpp::export]]
int fake_switch(SEXP x){

    // customize with different functions
    // Or, just pass different types into the template.
    switch( TYPEOF(x) ){
    case INTSXP: return count_me<INTSXP>(x); // integers
    case REALSXP: return count_me<REALSXP>(x); // numeric
    case STRSXP: return count_me<STRSXP>(x); // strings
    default: Rcpp::stop("type not handled"); // no support for obj
    }
    return -1; // should never be trigger but here to make the compiler happy
}

根据您要检查的 object 类型,可能有一个预定义的 Rf_isWhatever 宏,或者您可能需要使用 Rf_inherits(object, "Whatever") 宏,两者都在R 源代码,可通过 Rcpp header 获得。例如,

#include <Rcpp.h>

// [[Rcpp::export]]
int is_matrix(SEXP data) {
    return Rf_isMatrix(data) ? 0 : -1;
}

// [[Rcpp::export]]
int is_data_frame(SEXP x) {
    return Rf_inherits(x, "data.frame") ? 0 : -1;
}

/*** R

is_matrix(matrix(1:6, 2))
#[1] 0

is_matrix(data.frame(1:5))
#[1] -1

is_data_frame(data.frame(1:5))
#[1] 0

is_data_frame(matrix(1:6, 2))
#[1] -1

*/

作为参考,您可以check the source code查看可用的内容。