[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