From murdoch at stats.uwo.ca  Wed May 27 02:06:18 2009
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Tue, 26 May 2009 20:06:18 -0400
Subject: [Rd] passing "..." arguments to a function called by eval()
In-Reply-To: <4A1C5B85.7040208@rug.nl>
References: <4A1C5B85.7040208@rug.nl>
Message-ID: <4A1C83FA.9010204@stats.uwo.ca>

On 26/05/2009 5:13 PM, Richard Morey wrote:
> Hi everyone,
> 
> I am starting learn to call C code from within R. So far, I've been 
> trying toy problems to see if I can get them to work. One of the things 
> I'd like to do is pass an arbitrary R function to C, evaluate the value 
> in the C code using eval, and then return it. I also want to allow an 
> arbitrary number of arguments to the function using "...".
> 
> The code for my toy package looks like this:
> ########## R code, in pkg/R directory
> dTest <-
> function(x,...){
>     retVal    = .Call("dTestC",x[1],dnorm,...,rho=new.env(),PACKAGE="pkg")
>     return(retVal)
> }
> 
> ########## C code, in pkg/src directory
> 
> SEXP dTestC(SEXP dblX, SEXP funFn, SEXP dots, SEXP rho);

I wouldn't expect that to work, though it might if .Call is doing fancy 
things with the args.  The way I'd do it is to pass list(...) as a 
single argument to .Call, and within your C code, extract the elements. 
  It would make the call to funFn more complicated (it wants a pairlist 
of arguments, list(...) will be a vector list), but it looks safer than 
what you did.

There's an example in the Writing R Externals manual at the end of 
section 5.10.2 using ... with .External.  (It mentions using list(...) 
with .Call.)

Duncan Murdoch

> 
> /*--------------------------*/
> 
> 
> SEXP dTestC(SEXP dblX, SEXP funFn, SEXP dots, SEXP rho){
> 
>   SEXP retVal;
>   SEXP R_fcall;
> 
>   PROTECT(retVal = NEW_NUMERIC(1));
>   PROTECT(R_fcall = lang3(funFn, R_NilValue, R_NilValue));
>   SETCADR(R_fcall, dblX);
>   SETCADDR(R_fcall, dots);
>   retVal = eval(R_fcall, rho);
>   UNPROTECT(2);
> 
>   return(retVal);
> 
> }
> 
> ########################
> 
> When I call the dTest() function, the first required argument and the 
> first optional argument are both used, but not the ones after that.
> 
> I'm modeling this after what I found in the 'HI' package. I don't 
> understand a few few things. First, the C code used by the arms() 
> function in the HI package somehow manages to evaluate an R function, 
> with "..." arguments, without passing the SEXP dots argument. I haven't 
> been able to figure out how, looking at the source.
> 
> Second, in the Rinternal documents it mentions that  "..." is one 
> argument.  So, I figured I could get away with doing what I've done 
> above, and the SETCADDR function would set all the arguments in "..." in 
> one go. This is evidently wrong.
> 
> How can I do what I want to do? I know the HI package does it, but I 
> don't know how. I might pass all the arguments as members of one list, 
> but that seems like a waste. What am I doing/thinking wrong here? What's 
> the best way to do what I want to do?
> 
> Thanks for your help,
> 
> Richard
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] passing "..." arguments to a function called by eval()
Duncan Murdoch