Using C structs with FD 2.0 FFI 
Author Message
 Using C structs with FD 2.0 FFI

Hello all,

So far I have been very impressed with the Harlequin Dylan C FFI.  But I
have started playing with structs now and am having a problem getting a
simple example to work.  When I try to run the Dylan code below, I get a
"Dylan error: No next method" error.  There is no way to debug it in the
de{*filter*}.  Can someone tell me what I am doing wrong?  I assume I am
doing something stupid, but I don't see it.

-------------------- C code --------------------
typedef struct {
  double count;

Quote:
} Statistics;

int ReadStats (Statistics* stats) {
  stats->count = 123;
  return 1;

Quote:
}

-------------------- Dylan code --------------------
define C-struct <Statistics>
  slot count :: <C-double>;
  pointer-type-name: <Statistics*>;
end;

define C-function read-stats
  output parameter stats :: <Statistics*>;
  result value :: <C-int>;
  c-name: "ReadStats"
end;

define method main () => ()
  format-out("started...\n");
  let (result, stats) = read-stats();
  format-out("stats %=\n", stats.count);
end method main;

Sent via Deja.com http://www.*-*-*.com/
Before you buy.



Sat, 21 Sep 2002 03:00:00 GMT  
 Using C structs with FD 2.0 FFI

Quote:

> Can someone tell me what I am doing wrong?  

Cut down to a simple case:

---------------8<--------------
define c-struct <statistics>
  slot count :: <c-double>;
  pointer-type-name: <statistics*>;
end;

define method main () => ()
    pointer-value(make(<statistics*>));
end;
---------------8<--------------

This produces the error of no next-method(). It looks like no
pointer-value method is being added for <statistics*>. I'm pretty sure
this code should work but it doesn't. The pointer-value for a
<statistics*> should return an instance of  <statistics>.

By the way, with the code you posted, I think your output parameter
should not be an output parameter. The C code:

Quote:
> int ReadStats (Statistics* stats) {
>   stats->count = 123;
>   return 1;
> }

does not actually return a statistics* - it sets a value in the member
of the statistics*. So your Dylan interface should look like:

  define C-function read-stats
    parameter stats :: <Statistics*>;
    result value :: <C-int>;
    c-name: "ReadStats"
  end;

And call it with something like:

  with-stack-structure( stats :: <statistics*>)
    let result = read-stats(stats);
    format-out("%= %=\n", result, stats.count);
  end;

I tested this just now and it works fine. If you wanted an output
parameter type code, it would be used in a situation like:

  extern "C" int ReadStats (Statistics** stats) {
     Statistics* s = new Statistics;
     s->count = 123;
     *stats = s;
     return 1;
  }

Hope that helps,
Chris.
--
http://www.double.co.nz/dylan



Sun, 22 Sep 2002 03:00:00 GMT  
 Using C structs with FD 2.0 FFI

Quote:
> Hello all,

> So far I have been very impressed with the Harlequin Dylan C FFI.  But I
> have started playing with structs now and am having a problem getting a
> simple example to work.  When I try to run the Dylan code below, I get a
> "Dylan error: No next method" error. [...]

I think the problem is that stats isn't an output parameter as such (i.e.
you're not doing *stats = my_stats_struct anywhere in the function)[*].
ReadStats() expects to receive a pointer to a pre-allocated structure and
all it does is modify that struct with a new value for count.

So step one is to remove the "output" adjective from the function
declaration:

define C-function read-stats
  parameter stats :: <Statistics*>;
  result value :: <C-int>;
  c-name: "ReadStats"
end;

Step two is to allocate a structure and pass it in:

define method main () => ()
  format-out("started...\n");
  with-stack-structure (stats :: <Statistics*>)
    let result = read-stats(stats); // now only returns one value
    format-out("stats %=\n", stats.count);
  end;
end method main;

As the name of the macro suggests, with-stack-structure allocates a
temporary struct live only within the macro. Use make(<Statistics*>)
and delete(stats) for manual control over the lifetime of the struct.

Hope this helps,

-- Keith

[*] I guess the uninformative no next method error is a result of the
implementation trying to dereference a pointer to a struct (to extract
the output value) when it doesn't actually support manipulating structs by
value in this situation.

Quote:
> -------------------- C code --------------------
> typedef struct {
>   double count;
> } Statistics;

> int ReadStats (Statistics* stats) {
>   stats->count = 123;
>   return 1;
> }

> -------------------- Dylan code --------------------
> define C-struct <Statistics>
>   slot count :: <C-double>;
>   pointer-type-name: <Statistics*>;
> end;

> define C-function read-stats
>   output parameter stats :: <Statistics*>;
>   result value :: <C-int>;
>   c-name: "ReadStats"
> end;

> define method main () => ()
>   format-out("started...\n");
>   let (result, stats) = read-stats();
>   format-out("stats %=\n", stats.count);
> end method main;



Sun, 22 Sep 2002 03:00:00 GMT  
 Using C structs with FD 2.0 FFI
Dear Chris and Keith,

Thank you so much for your help, and clarifying that I should just use
an input parameter.  I'm not sure why I thought I should use an output
parameter, but that is what I thought.  I think why I went about it that
way was that I wanted the dylan function wrapper to allocate the struct
and then return the struct after it called the C function.  But now I
know the right way, and it is easy enough.

thanks again!

Sent via Deja.com http://www.deja.com/
Before you buy.



Sun, 22 Sep 2002 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. c-ffi question involving c-struct

2. FFI c-struct convenience classes? OO, not with-

3. FD 2.0 speed

4. FFI question in ACL/W 2.0

5. system:fd-stream-fd

6. Bigloo and Opengl (using glut and the c ffi)

7. problems using FFI for Win32 calls in MITscheme7.4

8. Using the clp(FD) solver

9. Using or closing a previously opened fd

10. anyone using FFI on Silicon Graphics?

11. to CS: or not to CS: in F-PC assembler

12. Nested structs and struct.pack

 

 
Powered by phpBB® Forum Software