Skip to content

correct C function usage

4 messages · Ido M. Tamir, Brian Ripley, Martin Maechler

#
Hello,
I am not sure if I am interfacing with C correctly and _safely_ 
or if there is a better way esp. with regards to terminating 
the "returned" array.

I am trying to fill an int array with values whose actual size
is determined in the C function and is always maximally as large
as length(values).

I also don't understand the purpose of $ab in the example:
conv <- function(a, b)
       .C("convolve",
      -snip-
          ab = double(length(a) + length(b) - 1))$ab




void testFill(int *values, int *newvalues, int* endposition ){
         newvalues[0] = 1;
         newvalues[1] = 2;
         *endposition = 2;
}

dyn.load("../testFill.so")

testTestFill <- function(){
  tempfilled <- testFillC( c(30:40))
  realfilled <- tempfilled$newvalues[1:tempfilled$endposition]
  return(realfilled)
}

testFillC <- function(a){
  .C("testFill", as.integer(a), newvalues=integer(length(a)), 
endposition=integer(1))
}


Thank you very much in advance
Ido Tamir
#
On Tue, 13 Dec 2005, Ido M. Tamir wrote:

            
You need to pass the length to the C routine and check you do not 
overwrite it.  (As in the parts you -snip-ed below.)
.C returns a list, an element for each argument after the first, named if 
the arguments were named.  So this selects the (copy) of the vector sent 
back as the last argument of the C function.
What do testFillC(1) or testFillC(logical(0)) do?
#
On Tuesday 13 December 2005 22:35, you wrote:
Thats undefined - probably a segmentation fault. 

Thank you very much for your answers.

I was trying to cut down my actual function so readers could focus
on what I was seeing as the main problem: terminating the array.
I was hoping that somebody would tell me that I only have to terminate
the array in the C function somehow and the R part would recognize
that automagically - and no more passing lengths explicitly around and 
copying arrays up to  length - e.g (ignoring wrong arguments):

void testFill(int *values, int *newvalues ){
         newvalues[0] = 1;
         newvalues[1] = 2;
         newvalues[2] =  '\0';
 }

testTestFill <- function(){
  realfilled <- testFillC( 1:10 ) 
  return(realfilled)
 }

testFillC <- function(a){
 .C("testFill", as.integer(a), newvalues=integer(length(a)))$newvalues
 }

But I tried this and it does not help.

sincerely, 
Ido Tamir
#

        
Ido> On Tuesday 13 December 2005 22:35, you wrote:
>> On Tue, 13 Dec 2005, Ido M. Tamir wrote:
>> > Hello,
    >> > I am not sure if I am interfacing with C correctly and _safely_
    >> > or if there is a better way esp. with regards to terminating
    >> > the "returned" array.
    >> 
    >> You need to pass the length to the C routine and check you do not
    >> overwrite it.  (As in the parts you -snip-ed below.)

    >> > testFillC <- function(a){
    >> >  .C("testFill", as.integer(a), newvalues=integer(length(a)),
    >> > endposition=integer(1))
    >> > }
    >> 
    >> What do testFillC(1) or testFillC(logical(0)) do?
    Ido> Thats undefined - probably a segmentation fault. 

    Ido> Thank you very much for your answers.

    Ido> I was trying to cut down my actual function so readers could focus
    Ido> on what I was seeing as the main problem: terminating the array.
    Ido> I was hoping that somebody would tell me that I only have to terminate
    Ido> the array in the C function somehow and the R part would recognize
    Ido> that automagically - and no more passing lengths explicitly around and 
    Ido> copying arrays up to  length .............

    Ido> .............

If you want this (and for other reasons), 
the use of  .Call()  instead of .C() is highly recommended.

With .Call() you get proper "R objects" on the C side which you
can "interrogate" for LENGTH() but also any other attributes().
On return, the result of .Call() can be any R object you might
want to construct from C.

Doug Bates (and many others) has found this to be particularly
fruitful when working with S4 class objects.
And of course, that has been designed to work like this by John
Chambers himself at the time S4 was designed and "The Green
Book" was written.  AFAIK, .Call() was part of the S4 wave
(with which I mean other innovations than just the S4 OO system).

Martin Maechler, ETH Zurich