[Rd] returning NULL from .Call call

From: Oleg Sklyar <osklyar_at_ebi.ac.uk>
Date: Tue 15 Mar 2005 - 23:31:46 GMT


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@ebi.ac.uk

______________________________________________
R-devel@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Received on Wed Mar 16 12:26:42 2005

This archive was generated by hypermail 2.1.8 : Mon 20 Feb 2006 - 03:21:02 GMT