Re: [Rd] how to call a function from C

From: <luke_at_stat.uiowa.edu>
Date: Thu, 14 Jan 2010 11:38:20 -0600 (CST)

On Thu, 14 Jan 2010, Romain Francois wrote:

> On 01/14/2010 12:42 PM, Laurent Gautier wrote:
>>> Hi,
>>>
>>> In Rcpp, we now have a "Function" class to encapsulate functions
>>> (they cover all three kinds, but this may change).
>>
>> Just a note on that: there is probably no hurry to do so.
>> rpy2 is also having CLOSXP, BUILTINSXP, and SPECIALSXP represented as
>> one function-like class and seems to be behave reasonably while a lot of
>> other things seem more urgent to sort out.
>>
>>> To call the function, what we do is generate a call with the function
>>> as the first node and then evaluate the call.
>>>
>>> SEXP stats = PROTECT( R_FindNamespace( mkString( "stats") ) ); SEXP
>>> rnorm = PROTECT( findVarInFrame( stats, install( "rnorm") ) ) ; SEXP
>>> call = PROTECT( LCONS( rnorm, CONS( ScalarInteger(10),
>>> CONS(ScalarReal(0), R_NilValue ) ) ) ); SEXP res = PROTECT( eval(
>>> call , R_GlobalEnv ) ); UNPROTECT(4) ; return res ;
>>>
>>> It works, but I was wondering if there was another way. I've seen
>>> applyClosure, but I'm not sure I should attempt to use it or if using
>>> a call like above is good enough.
>>
>> Using R_tryEval() will let you evaluate an expression in a given
>> environment, as well as capture an eventual error occurring during its
>> evaluation (and translate it as an exception).
>
> Sure. I did not want to over-complicate the question.
>
> I'm currently reviewing tryEval and its underlying R_TopLevelExec which does
> not give me enough : when the error occurs, it'd be useful that the function
> returns the condition object instead of NULL.

R_TopLevelExec, and hence R_tryEval, don't quite do what some users expect and maybe would like. There are two issues.

The TopLevel part means that conceptually this call runs in its own stack, which means things like calling error handlers set up outside this call are not visible, and Sys.whatever functions don't see the rest of the stack (or at least should not). A call to one of these is conceptually a bit like asking a separate thread to evaluate the expression and waiting for the result. (I believe his mechanism was added to handle finalizer code in the GC, where this makes sense, but I may have my history wrong.)

The other issue is that what R_tryEval catches is not errors, it is longjmp attempts. The vast majority of these will come from attempts to pass errors to exiting handlers, but there are other possibilities, such as invoking an abort restart (which jumps to top level).

It might be useful to provide a C level interface for catching errors as well as other jumps and for allowing C code to do cleanup operations and then continue those jumps if appropriate, but getting that right is fairly tricky and certainly hasn't risen high enough on my priority list to warrant the investment of time. The interface would have to abstract over implementation details though: we definitely do not want to expose and commit to current details of the context stack implementation.

luke

>
>>> Romain
>>>
>>> PS: using Rcpp's C++ classes you would express the code above as :
>>>
>>> Environment stats("package:stats") ; Function rnorm = stats.get(
>>> "rnorm" ) return rnorm( 10, 0.0 ) ;
>>
>> Feel free to snoop in rpy2's rpy/rinterface/rinterface.c and look for
>> "do_try_eval". The behavior looks very similar, the above snippet in
>> rpy2 would write like:
>>
>> from rpy2.robjects.packages import importr
>> stats = importr('stats')
>> stats.rnorm(10, 0.0)
>
> nice
>
>

-- 
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      luke_at_stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Received on Thu 14 Jan 2010 - 17:42:26 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Thu 14 Jan 2010 - 20:10:13 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive