[Rd] returning NULL from .Call call

Oleg Sklyar osklyar at ebi.ac.uk
Wed Mar 16 00:31:46 CET 2005


Dear R developers,

I've just encountered one "feature" of R-C extensions. If it is known, I 
would be thankful for any hints why it works this way (I found the way 
around, which is also mentioned here, but maybe it is not the best one). 
If it is however unknown, it might be considered for a "wish list".

Consider a simple "aka" C function (the original implementation loads 
complex data structures and there could be other causes of trouble apart 
from non-existing files):

SEXP loadData(SEXP fileName) {
    int* data = NULL;
    try {
       // try to open the file and read the data into 'data'
    } catch(...) {
       std::cout << "Load failed (ANY REASON) - returning NULL" << 
std::endl;
       return NULL;
    }
    // operation successful, but the size of data can be nil
    if(data == NULL)
       return NULL;
    SEXP result = allocVector(INTSXP, numOfDataPoints);
    PROTECT(result);
    // copy data from 'data' into 'result'
    delete[] data;
    UNPROTECT(1);
    return result;
}

This function will nicely return a data array if no load problems occur 
and data is more than nil. If it is not the case I would be happy to 
receive a NULL as indication that the function didn't succeed, which I 
can then check with is.nul(...). I would consider it logical for SEXP, 
which is a pointer (in this case to a non-existing structure). However, 
trying to return NULL causes 'Segmentation Fault' without any further 
message and R-session closes. The question is, what would be a working 
way to return anything like NULL, something to check with is.null(...)?

Now the way around (just in case it might be of interest), slightly 
modified function returning numeric(0) on fail:

SEXP loadData(SEXP fileName) {
    // prerecreate and protect a non-NULL return value: numeric(0)
    SEXP result = allocVector(INTSXP, 0);
    PROTECT(result);
    int* data = NULL;
    try {
       // try to open the file and read the data into 'data'
    } catch(...) {
       std::cout << "Load failed (ANY REASON) - returning NULL" << 
std::endl;
       // unprotect and return numeric(0)
       UNPROTECT(1);
       return result;
    }
    // operation successful, but the size of data can be nil
    // unprotect old value to enable garbage collector to kill it sooner 
or later
    UNPROTECT(1);
    if(data == NULL)
       return result;
    // recreate and protect the return value
    result = allocVector(INTSXP, numOfDataPoints);
    PROTECT(result);
    // copy data from 'data' into 'result'
    delete[] data;
    UNPROTECT(1);
    return result;
}

This function always has something to return and it works, but not 
really elegantly and returning wrong data when fails.

Thanks in advance for any comments.
Regards
Oleg

-- 
Dr Oleg Sklyar
European Bioinformatics Institute
Wellcome Trust Genome Campus
Hinxton, Cambridge, CB10 1SD
England
phone/fax  +44(0)1223 49 4478/4468
e-mail osklyar at ebi.ac.uk



More information about the R-devel mailing list