Of course one problem is that R hides things that I need for this, such as R_HandlerStack and R_ReturnedValue.
I understand they have to be hidden, in which case can we have an exposed mechanism similar to what R_ToplevelExec does, but with the added functionality of giving access to the condition where R_ToplevelExec would return TRUE. Would someone be willing to review a patch to R with this added functionality. Please. In any case, I still would like some comments about my initial question about R_NilValue use in gotoExitingHandler(R_NilValue, call, entry); Romain Le 26 févr. 2014 à 09:41, Romain François <[email protected]> a écrit : > Hello, > > I’m trying to leverage R_ToplevelExec to implement C level try/catch. > > The way it is implemented allows for running a function in a top level > context. This context gets an empty handler stack, so either the function > runs correctly or it jumps. When it jumps, it does not find a handler, so it > jumps to the top level context. > > R does not allow me to call begin context and end context directly, so > instead what I do is call R_ToplevelExec, grab the global context inside the > function, install my own handler that I don’t set to be a calling one, > pretend this context is a CTXT_FUNCTION. > > Eventually I get to jump fun, so that I can later on grab the condition from > R_ReturnedValue. > > This works well in the « not simple error » case, i.e. if I call stop( > simpleError(...) ), but with simple errors, i.e. calls to Rf_error internally > or bare calls to stop( "vvzvz" ) I can’t access the error. > > And this boils down to this call: > > gotoExitingHandler(R_NilValue, call, entry); > > inside vsignalError : > > static void vsignalError(SEXP call, const char *format, va_list ap) > { > char localbuf[BUFSIZE]; > SEXP list, oldstack; > > oldstack = R_HandlerStack; > Rvsnprintf(localbuf, BUFSIZE - 1, format, ap); > while ((list = findSimpleErrorHandler()) != R_NilValue) { > char *buf = errbuf; > SEXP entry = CAR(list); > R_HandlerStack = CDR(list); > strncpy(buf, localbuf, BUFSIZE - 1); > /* Rvsnprintf(buf, BUFSIZE - 1, format, ap);*/ > buf[BUFSIZE - 1] = 0; > if (IS_CALLING_ENTRY(entry)) { > if (ENTRY_HANDLER(entry) == R_RestartToken) > return; /* go to default error handling; do not reset stack */ > else { > SEXP hooksym, hcall, qcall; > /* protect oldstack here, not outside loop, so handler > stack gets unwound in case error is protect stack > overflow */ > PROTECT(oldstack); > hooksym = install(".handleSimpleError"); > PROTECT(qcall = LCONS(R_QuoteSymbol, > LCONS(call, R_NilValue))); > PROTECT(hcall = LCONS(qcall, R_NilValue)); > hcall = LCONS(mkString(buf), hcall); > hcall = LCONS(ENTRY_HANDLER(entry), hcall); > PROTECT(hcall = LCONS(hooksym, hcall)); > eval(hcall, R_GlobalEnv); > UNPROTECT(4); > } > } > else gotoExitingHandler(R_NilValue, call, entry); // <<< HERE > } > R_HandlerStack = oldstack; > } > > Would it be possible to construct a simple condition instead of passing down > R_NilValue so that I can grab this error and deal with it. > > The alternative is to set the handler to be a calling one, but I’d like to > avoid that as much as possible as this means going back to the R side of > things just to get access to the condition. > > My code is here: https://gist.github.com/romainfrancois/9225811 > > I have only tested this on OSX with R-devel. The code only uses R internal > api (not Rcpp*). > > So down to what I’d like you to consider please if you are still reading > here. Can we feed gotoExitingHandler with something more interesting than > NULL. please. > > > > The end game is to add one layer of abstraction, e.g. pass to R_ToplevelExec > a function that first deals with contexts, then calls an actual function. > Combining this with lambda functions in C++ will make quite a nice and > elegant way to handle error handling at the C++ level. > > I can provide the code that would create the simpleError, this is just making > a simple VECSXP with names and classes, no big trouble here. > > Romain > > ______________________________________________ > [email protected] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ [email protected] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
