One hassle I could do without is the necessity of writing C wrapper functions like this: void fameInit(int *status){ cfmini(status); return; } when I want to call a library function (cfmini, in this case) that takes an int argument. The .C interface only lets me pass a pointer to an int, rather than the int itself. Is there any chanch that .C could be enhanced to allow passing arguments by value to the compiled code? It would make some of my stuff much simpler. -- Jeff
On 17/08/2009 10:23 AM, Jeffrey J. Hallman wrote:> One hassle I could do without is the necessity of writing C wrapper functions > like this: > > void fameInit(int *status){ > cfmini(status); > return; > } > > when I want to call a library function (cfmini, in this case) that takes an > int argument. The .C interface only lets me pass a pointer to an int, rather > than the int itself. > > Is there any chanch that .C could be enhanced to allow passing arguments by > value to the compiled code? It would make some of my stuff much simpler.What you have above doesn't work (you passed the pointer, not the value), but it's hardly complex. I don't think the effort of extending .C in that way would be a worthwhile use of time. Duncan Murdoch
On Mon, Aug 17, 2009 at 9:23 AM, Jeffrey J. Hallman<jhallman at frb.gov> wrote:> One hassle I could do without is the necessity of writing C wrapper functions > like this: > > void fameInit(int *status){ > ?cfmini(status); > ?return; > } > > when I want to call a library function (cfmini, in this case) that takes an > int argument. ?The .C interface only lets me pass a pointer to an int, rather > than the int itself.> Is there any chanch that .C could be enhanced to allow passing arguments by > value to the compiled code? ?It would make some of my stuff much simpler.I suppose that if you design a new interface and submit patches to the code in R that does the interfacing, it could be done. However, I imagine you would find it easier to continue to write short interface functions like that. :-) (By the way, the "return;" is redundant in a C function that returns void.) You should remember that internally there are no scalar objects in R - everything is a vector. If you use the .Call interface, which initially is more complicated but eventually helps you simplify your code, arguments are passed and values returned as SEXPs and you can use convenient utilities like asInteger which make your R code simpler because they extract a scalar integer value from an SEXP, coercing if necessary. So, if you have a C function that takes two integer arguments and returns an integer you can write the C interface function as SEXP R_callable_foo(SEXP a, SEXP b) { return ScalarInteger(foo(asInteger(a), asInteger(b))); } It is not surprising that you need to write interface code - it is remarkable that it works at all.
Jeff, On Aug 17, 2009, at 10:23 , Jeffrey J. Hallman wrote:> One hassle I could do without is the necessity of writing C wrapper > functions > like this: > > void fameInit(int *status){ > cfmini(status); > return; > } > > when I want to call a library function (cfmini, in this case) that > takes an > int argument. The .C interface only lets me pass a pointer to an > int, rather > than the int itself. > > Is there any chanch that .C could be enhanced to allow passing > arguments by value to the compiled code?IMHO close to 0, because there is not such a thing as "scalar int" in R. All objects in R are arrays (in C speak), so in all three: foo(integer(0)), foo(1L), foo(1:10) the argument is of the same type: integer vector (analogously C type int[]). In fact .C should preferably not be used for wrappers like the one you suggested, because it's more prone to errors and much less flexible than .Call which gives you all you want including the control over duplication and the length of the supplied arguments. (There are some packages that can generate wrappers from function arguments or header files - maybe the authors can comments on that if they wish). Cheers, Simon
replying to myself here, in lieu of replying to several others jhallman at frb.gov (Jeffrey J. Hallman) writes:> One hassle I could do without is the necessity of writing C wrapper functions > like this: > > void fameInit(int *status){ > cfmini(status); > return; > } > > when I want to call a library function (cfmini, in this case) that takes an > int argument. The .C interface only lets me pass a pointer to an int, rather > than the int itself. > > Is there any chanch that .C could be enhanced to allow passing arguments by > value to the compiled code? It would make some of my stuff much simpler.Of course I realized right after I posted that my example was incorrect. Since the cfmini() function takes a pointer to an int, all I needed was this: status <- .C("cfmini", status = as.integer(0))$status However, I do have functions where this can't be done, because the library function being called takes one or more parameters by value, not by reference. For example, I had to write this wrapper: void fameCloseDatabase(int *status, int *key){ cfmcldb(status, *key); return; } where the "key" argument to cfmcldb() is an int, not a pointer. As you probably realize, cfmcldb() is not something I wrote: it's part of the FAME Host Language Interface (chli) provided by Sungard, the vendor of the FAME time series database. My point, which I clearly did not make very well, since all of the replies so far have missed it, is that if .C() could pass arguments by value as well as by reference, I could write the fame package (an interface to the FAME database) entirely in R, as I'd be able to call any of the chli functions directly, without having to write C wrappers. This would make if much easier to debug the package and get it working correctly on Windows, where I can't seem to get it to compile correctly any more. I surely cannot be the only package writer who has to interface to external libraries and would rather write the interface in R than in C. Do we not all see the virtues of doing almost everything in R itself, rather than writing parts of the system in other languages and systems? Why else would Ripley undertake all the recent work to parse .Rd files in R rather than in Perl, and why do people work on things like gWidgets? -- Jeff