From murdoch at stats.uwo.ca  Tue Aug 18 16:34:44 2009
From: murdoch at stats.uwo.ca (Duncan Murdoch)
Date: Tue, 18 Aug 2009 10:34:44 -0400
Subject: [Rd] Calling C functions with value parameters
In-Reply-To: <xmrskfpp6sl.fsf@mralx1.rsma.frb.gov>
References: <xmrws52plho.fsf@mralx1.rsma.frb.gov>
	<xmrskfpp6sl.fsf@mralx1.rsma.frb.gov>
Message-ID: <4A8ABC04.5090602@stats.uwo.ca>

On 18/08/2009 9:53 AM, Jeffrey J. Hallman wrote:
> 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?

Rd files are now parsed in C, not in R, and the parser was written by 
me, not by Brian, but you do have a good point:  reducing our reliance 
on external tools that aren't under our control is generally a good 
thing.  It's inconceivable that anyone will do the work to rewrite R not 
to rely on C, but within a year or two we probably won't rely on Perl.

However, the problem with your suggestion is that it is not at all easy 
to do.  C has a much richer function calling interface than R does. 
Currently .C supports a minimal part of it, and we could support more, 
but it isn't at all easy.  How do you simulate a general argument list 
to a C function in C code?  (I don't know if it's possible in a portable 
way.)  The current .C implementation has a long list of possible calls: 
  zero args, one arg, two args, etc.  If we knew we were working with a 
specific version of gcc on a specific platform, we could simplify it a 
lot, but we don't.  R compiles on all sorts of different platforms, with 
compilers using all sorts of different calling conventions.  It is just 
not feasible to write portable code to do general calls.

We could expand the list of calls that we do support, but it's a lot of 
work, and there would always be someone asking for others.   As Doug 
said, it is not surprising that you need to write interface code - it is
remarkable that it works at all.

Duncan Murdoch

>



[Rd] Calling C functions with value parameters
Duncan Murdoch