Calling C functions with value parameters

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Calling C functions with value parameters

Jeffrey J. Hallman-2
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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Calling C functions with value parameters

Duncan Murdoch
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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Calling C functions with value parameters

Douglas Bates-2
In reply to this post by Jeffrey J. Hallman-2
On Mon, Aug 17, 2009 at 9:23 AM, Jeffrey J. Hallman<[hidden email]> 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.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Calling C functions with value parameters

Simon Urbanek
In reply to this post by Jeffrey J. Hallman-2
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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Calling C functions with value parameters

Jeffrey J. Hallman-2
In reply to this post by Jeffrey J. Hallman-2
replying to myself here, in lieu of replying to several others

[hidden email] (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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: Calling C functions with value parameters

Duncan Murdoch
On 18/08/2009 9:53 AM, Jeffrey J. Hallman wrote:

> replying to myself here, in lieu of replying to several others
>
> [hidden email] (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

>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel