On Tue, 15 Mar 2005, Oleg Sklyar wrote:
> Dear R developers,
>
> I've just encountered one "feature" of R-C extensions.
What feature is that? (It really is not clear from your description.)
NULL in R is expressed as R_NilValue in C. What did you do when `trying
to return NULL'? NULL in C is not a valid value for a SEXP pointer, of
course.
This is documented in `Writing R Extensions', and there are many examples
of it around.
> 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
>
>
--
Brian D. Ripley, ripley@stats.ox.ac.uk
Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/
University of Oxford, Tel: +44 1865 272861 (self)
1 South Parks Road, +44 1865 272866 (PA)
Oxford OX1 3TG, UK Fax: +44 1865 272595