[Rd] how to call a function from C

Romain Francois romain.francois at dbmail.com
Thu Jan 14 16:20:53 CET 2010


On 01/14/2010 03:50 PM, Dominick Samperi wrote:
> The Rcpp library in RcppTemplate (the package that Rcpp forked from)
> simplifies the process
> of calling functions from C++. The design goal was to enable users to
> focus on
> scientific problem solving rather than interface problems and low-level
> R internals (by
> hiding these details and documenting everything).

Hello Dominick,

In the Rcpp package, you'd call the rnorm function like this :

/* grab the environment called "package:stats" */
Environment stats("package:stats") ;
/* or like this if you want the namespace */
/* Environment stats = Environment::namespace_env("stats") ;*/

/* grab function called 'rnorm' from this environment */
Function rnorm = stats.get("rnorm" ) ;

/* call the function, about the same way you'd do in R
  *
  * > rnorm( 10L, sd = 100 )
  */
return rnorm( 10, Named( "sd", 100.0 ) ) ;

All involved SEXP are encapsulated in suitable C++ objects, such as 
Environment, Function, etc ... the user does not need to know about 
SEXP, does not need to care about the PROTECT/UNPROTECT dance, etc ...

Please let me know which of these three lines of C++ code you consider 
to be low level R internals.

It might be interesting that you post how you would invoke the same 
using RcppTemplate.

> The current Rcpp package is a mashup of the packages RcppTemplate (old
> version),
> inline, and RInside

It is not anything even kind of close to that.

There was code from the inline package at some point, but it is now back 
into inline, which has been improved to support easy inlining of code 
making use of Rcpp.

There is nothing of RInside in Rcpp, it goes the other way, RInside 
depends on Rcpp and uses its features to ease embedding R into an 
existing C++ application

The Rcpp package is under a lot of changes. See :
- http://dirk.eddelbuettel.com/blog/2010/01/12/#rcpp_0.7.2
- http://dirk.eddelbuettel.com/blog/2010/01/02/#rcpp_0.7.1
- 
http://romainfrancois.blog.free.fr/index.php?post/2010/01/13/Rcpp-0.7.2-is-out
- 
http://romainfrancois.blog.free.fr/index.php?post/2010/01/08/External-pointers-with-Rcpp
- 
http://romainfrancois.blog.free.fr/index.php?post/2009/12/29/new-things-in-Rcpp

> that involves a fair amount of low-level R hacking,
> and this is
> probably consistent with the preferences of most readers of this list.

Can you be more specific ?

The whole purpose of the package is to hide the R API. The user does not 
need to know the R API to use the classes of Rcpp. We however indeed use 
and abuse the R API a lot internally.

Romain

> If I am mistaken and there are any users of RcppTemplate please let me
> know, as I
> am thinking about reoganizing that package to minimize confusion with
> the fork.
>
> Thanks,
> Dominick
>
> On Thu, Jan 14, 2010 at 7:16 AM, Romain Francois
> <romain.francois at dbmail.com <mailto:romain.francois at dbmail.com>> 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.
>
>
>             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



More information about the R-devel mailing list