Как вернуть массив структур из .Call в C общую библиотеку в R - PullRequest
2 голосов
/ 04 января 2012

Как я могу вернуть массив struct из .Call функции в разделяемой библиотеке C и впоследствии использовать этот массив в R?

Например:

typedef struct{
    int    thing1;
    int    thing2;
    float  thing3;
    float  thing4;
    char   thing5;
    //... many more things of various simple types
} MY_STRUCT;

SEXP R_Calls_Me(SEXP args) {

    // Do stuff with args...

    // Create arrayOfMyStructs as what type??

    return arrayOfMyStructs;
}

Какой тип arrayOfMyStructs такой, что R может использовать его?

Кажется, что это обычная вещь, которую хотелось бы сделать, но я не могу найти никаких примеров этого в документации по написанию расширений R.

Ответы [ 2 ]

3 голосов
/ 04 января 2012

Как правило, вы создаете список (общий вектор) с компонентами, которые вы хотите вернуть. В вашем случае что-то вроде

SEXP res = PROTECT(allocVector(VECSXP, 5));
SET_VECTOR_ELT(res, 0, ScalarInteger(a.thing1));
SET_VECTOR_ELT(res, 1, ScalarInteger(a.thing2));
SET_VECTOR_ELT(res, 2, ScalarReal(a.thing3));
...
UNPROTECT(1)
return res;

Также принято присваивать имена вектору, например ::

const char *names[5] = { "thing1", "thing2", "thing3", "thing4", "thing5" };
SEXP sNames = PROTECT(allocVector(STRSXP, 5));
for (int i = 0; i < 5; i++) SET_STRING_ELT(res, i, mkString(names[i]));
setAttrib(res, R_NamesSymbol, sNames);
UNPROTECT(1);

Обратите внимание, что вы описываете не массив, а структуру. Массивы, как правило, гораздо проще передавать как векторы.

2 голосов
/ 04 января 2012

Вероятно, наиболее естественный способ сделать это - использовать внешние указатели. Вы вернете указатель на R, а затем код вашего приложения будет манипулировать этим. Несколько пакетов делают это сейчас, например, XML, h5r.

SEXP _h5R_make_ptr() {
    h5_holder* holder = (h5_holder*) Calloc(1, h5_holder);
    holder->id = 1;
    holder->is_file = 0;
    SEXP e_ptr = R_MakeExternalPtr(holder, R_NilValue, R_NilValue); 
    PROTECT(e_ptr);
    R_RegisterCFinalizerEx(e_ptr, h5R_finalizer, TRUE);
    UNPROTECT(1); 
    return e_ptr;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...