From romain.francois at dbmail.com  Thu Jan 14 13:16:29 2010
From: romain.francois at dbmail.com (Romain Francois)
Date: Thu, 14 Jan 2010 13:16:29 +0100
Subject: [Rd] how to call a function from C
In-Reply-To: <4B4F031F.7000202@gmail.com>
References: <mailman.31.1263466812.18774.r-devel@r-project.org>
	<4B4F031F.7000202@gmail.com>
Message-ID: <4B4F0B1D.8060108@dbmail.com>

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.

>> 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

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/KfKn : Rcpp 0.7.2
|- http://tr.im/JOlc : External pointers with Rcpp
`- http://tr.im/JFqa : R Journal, Volume 1/2, December 2009



[Rd] how to call a function from C
Romain Francois