How to get column names of an R list from C code

I need to write a C / C ++ function that will retrieve the column names of an R list.

From R, I want to do the following.

> dyn.load("R_list.dll")
> x = list(param1="value1", param2="value2", param3="value3")
> .Call("func", x)

and as an output I want to see "param1" "param2" "param3"how a names(x)function of R

> names(x) [1] "param1" "param2" "param3"

In my cpp file, I have the following

#include <R.h>
#include <Rinternals.h>
#include <Rdefines.h>

extern "C" __declspec( dllexport ) SEXP func(SEXP list)
{
    try
    {
        if (isNewList(list))
        {
            int n = length(list);
            printf("%d\n", n);
            for (int i=0; i<n; ++i)
                printf("%s\n", CHAR(STRING_ELT(VECTOR_ELT(list, i), 0)));
        }
        else
        {
            throw std::exception("'list' variable must be a list!");
        }       
    }
    catch(const std::exception& ex)
    {
        printf("Exception was thrown: %s\n", ex.what());
    }
    return R_NilValue;
}

How to get column names, not values, from C / C ++ code?

+4
source share
3 answers

All this Rf_getAttrib, R_NamesSymbolsee. Writing extensions the R :

library('inline')
listnames <- cfunction(signature(x="list"), "
   return Rf_getAttrib(x, R_NamesSymbol);
")

listnames(list(param1="value1", param2="value2", param3="value3"))
## [1] "param1" "param2" "param3"

As you can see, it Rf_getAttribreturns here a regular character vector that can be controlled with STRING_ELT.

+6
source

Even shorter is one statement, because Rcpp does all the conversion.

Rcpp:

R> library(Rcpp)

R> cppFunction('CharacterVector mynames(List l) { return l.attr("names"); }') 

:

R> mynames(list(a=1:3, b=runif(10), c=LETTERS))
[1] "a" "b" "c"
R> 

: , names():

R> cppFunction('CharacterVector mynames(List l) { return l.names(); }') 
R> mynames(list(a=1:3, b=runif(10), c=LETTERS))
[1] "a" "b" "c"
R> 
+2

A member function attrcan also be used for this (although @gagolews answer is clearly simpler):

require(inline)
l <- list(a=1:3, b=runif(10))
f <- cxxfunction(signature(x_ = "List"), plugin = "Rcpp", body = '
    Rcpp::List x(x_);
    CharacterVector names = x.attr("names");
    return names;
')
f(l)

# [1] "a" "b"
+1
source

Source: https://habr.com/ru/post/1543415/


All Articles