[Prev][Next][Index][Thread]
Re: 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. [...]
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.
> -------------------- 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;