I was still puzzled by the fact that HI managed to do it without using
complicated lists, so recombed the HI source to see what I missed the
first time.
HI defines a second function f=function(x) passedFun(x,...) and then
passes that to the C code using .Call. I had missed something subtle,
and was using
f=function(x,...) passedFun(x,...)
and passing that to .Call. That, of course, didn't work, leading me to
try to find the solution below. It is critical that you don't have ...
as an argument to the dummy function you define. That way, ... will be
in scope in the dummy function and you don't have to pass it to .Call.
Richard
Duncan Murdoch wrote:
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@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel