How to return a list or array from C block in Haskell's inline-c?

434 views Asked by At

How can I get a list or array from C block in Haskell's inline-c? In other words, how to construct complex data in C and work with it in Haskell. Something like this:

foo :: IO [Int]
foo = do
 what? <- [C.block| <what?> {
    ints = calloc(10, sizeof(int));
    // ...
    return <what?>;
  } |]
  return <what?>

I could wrap a pointer and a size in some Haskell type, but I'd like to work with the list in Haskell, print it, encode in JSON, etc.

1

There are 1 answers

7
Benjamin Hodgson On BEST ANSWER

Return a pointer to the array from your C code and use peekArray to marshal it to a list.

import Foreign.Marshal.Array
import Language.C.Inline

foo :: Int -> IO [Int]
foo size = [exp| int* { calloc($(int size), sizeof(int)) }] >>= peekArray size

peekArray accepts a pointer argument and a number of elements to read. It iteratively increments the pointer size times, pulling elements off the array using the type's Storable instance (in this case, Int).

It may be more efficient to turn your array into an unboxed Vector.