[Haskell-cafe] FFI ccall struct return by value on the stack?

Patrick Chilton chpatrick at gmail.com
Tue Jun 16 15:13:15 UTC 2020


I would return a malloced pointer. After that, it depends on what you want
to do with the Foo.

If you just want to pass it to other C stuff and don't want to read its
contents from Haskell, I would wrap it in an opaque ForeignPtr to be freed
or make sure it gets freed with a `bracket`. Then there's no awkwardness
with generating/updating a Storable instance.

If you need the contents from Haskell, peek it and free it immediately.
Haskell's alloca also allocates internally so it's not like it would be on
the stack in any case.

The important thing is that any bit of code that deals with raw pointers
with no cleanup registered must have async exceptions masked, otherwise if
one is thrown the memory will be leaked.

On Tue, Jun 16, 2020, 16:45 ☂Josh Chia (謝任中) <joshchia at gmail.com> wrote:

> Suppose I have the following C code:
>
> typedef struct Foo {
>     char* p1;  /* Some data on the heap. */
>     size_t s1; /* Size of data. */
>     char* p2;  /* More data on the heap. */
>     size_t s2;
> } Foo;
>
> /* Allocates and writes two pieces of data on the heap and returns them in
> a Foo. */
> Foo makeFoo(size_t x);
>
> Based on my limited understanding of Haskell FFI according to the Haskell
> 2010 Language Report (
> https://www.haskell.org/onlinereport/haskell2010/haskellch8.html), it is
> not possible to have a ccall for makeFoo() because Foo is not a
> marshallable foreign result type. Is my understanding correct?
>
> However, I believe I can have a ccall if I change makeFoo() to either of
> the following:
> Foo* makeFoo(size_t x);
> void makeFoo(Foo* out, size_t x);
>
> The first involves the C code allocating a Foo and returning a pointer to
> it (so now there's one more pointer for the C code to deallocate later in
> another function). The second involves the C code writing a Foo value to a
> piece of memory allocated in Haskell (possibly using
> Foreign.Marshall.Alloc.alloca). Both signatures work because Foo* is
> marshallable but are clumsier to use than the original signature. Is there
> just no way to return a struct by value on the stack? Is there a cleaner
> way than the above two?
>
> Josh
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20200616/b470d26c/attachment.html>


More information about the Haskell-Cafe mailing list