I'm looking for a complete working example of a Haskell FFI function that conceptually has signature: ByteString -> ByteString
, i.e. which:
- Takes as input an array of 8-bit unsigned integers which has been allocated on the 'c' heap (i.e. with a lifetime that exceeds the FFI invocation).
- Transforms the array into a
ByteString
(assuming thatByteString
can't feature directly in the FFI API). - Immutably transforms the
ByteString
in some manner (trivial example: reversing it). - Returns to the invoking 'c' function the transformed
ByteString
(or whatever FFI representation of it is required), such that it must be deleted on the 'c' side.
A Google search reveals a variety related and/or partial information, but the devil is very much in the details here: I haven't been able to find a relevant MWE (of what one would consider an elementary FFI application) anywhere.
EDIT: One commenter has kindly pointed out that ByteString already encapsulates a pointer and a length.
That leads to some more concrete questions:
Q1. What should the corresponding 'c' function signature for
ByteString -> ByteString
be?
e.g. is it necessary to explicitly define ByteString on the 'c' side?
struct ByteString { uint8 * array; size_t length };
ByteString cfunc(ByteString arg);
It doesn't look like translating this directly yields a valid FFI call. For:
foreign export ccall cfunc :: ByteString -> ByteString
the compiler error is "ByteString cannot be marshalled in foreign call".
Q2 Does arg have to be somehow converted to a ByteString on the Haskell side or does the fact that it's (intended to be) structurally isomorphic suffice?