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 [EMAIL PROTECTED]
______________________________________________ R-devel@stat.math.ethz.ch mailing list https://stat.ethz.ch/mailman/listinfo/r-devel