0

I'm looking for a complete working example of a Haskell FFI function that conceptually has signature: ByteString -> ByteString, i.e. which:

  1. 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).
  2. Transforms the array into a ByteString (assuming that ByteString can't feature directly in the FFI API).
  3. Immutably transforms the ByteString in some manner (trivial example: reversing it).
  4. 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?

NietzscheanAI
  • 966
  • 6
  • 16
  • 1
    What is the question? What have you tried? What are you stuck on? – Noughtmare Jun 13 '21 at 12:00
  • 1
    ByteString already is a "'c' array", as you call it. Except it is also stores the length of the array. You can see here https://hackage.haskell.org/package/bytestring-0.11.1.0/docs/src/Data.ByteString.Internal.html#ByteString. `ForeignPtr Word8` is the pointer to the array. – pedrofurla Jun 13 '21 at 12:24
  • 1
    You can also find several examples of FFI usage https://hackage.haskell.org/package/bytestring-0.11.1.0/docs/src/Data.ByteString.Internal.html#c_strlen – pedrofurla Jun 13 '21 at 12:31
  • @pedrofurla Thanks - that's useful to know. But it's still not clear what the corresponding 'c' function signature for ByteString -> ByteString would actually look like. Would it be something like: struct ByteString { uint8 * array; size_t length }; ByteString cfunc(ByteString arg); or something else? As I say in the question, there's no shortage of partial answers, but that still leaves a combinatorial explosion of possibilities in getting something actually working. – NietzscheanAI Jun 13 '21 at 14:54
  • 2
    The signature you wrote is essentially correct. The compiler complains because your custom type needs a custom marshaller (particularly, a `Storable` instance). The FFI docs are pretty clear on this, see eg [here](https://stackoverflow.com/questions/6243815/using-the-haskell-ffi-to-marshal-structs-also-how-to-use-funptr). This also answers your 2nd question - your custom type does have to be converted, and it is precisely the Storable instance which does tge conversion. – user2407038 Jun 13 '21 at 16:39
  • 1
    BTW, I introduced myself into Haskell FFI by a mix of FFI docs, [language-c-inline](https://hackage.haskell.org/package/language-c-inline) which is a nice inlining tool for C code and example usages of this tool in [haskell-postal](https://hackage.haskell.org/package/haskell-postal). – pedrofurla Jun 13 '21 at 21:31
  • @user2407038 Adding instance Storable ByteString still results in the same compiler error ... – NietzscheanAI Jun 14 '21 at 10:52
  • @NietzscheanAI If you have a complete program, including an `instance Storable ByteString`, and it fails to compile, I suggest you include that full program in your question. Also on a second reading your type should be `Ptr ByteString -> Ptr ByteString` – user2407038 Jun 14 '21 at 15:18

0 Answers0