3

As far as I can tell, Lwt_bytes seems to use the same type as Cstruct (or probably uses cstruct itself), but some some reason I can't make the two of them work together :

Lwt_io.write_from_exactly out b.Cstruct.buffer 0 16


Error: This expression has type
         Cstruct.buffer =
           (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
           Bigarray.Array1.t
       but an expression was expected of type bytes

Isn't bytes that exact same type ? How can I make that work ? I'm trying to use Cstruct instead of Lwt_bytes for the convenience of Cstruct.LE, which bytes doesn't seem to have. Thanks

Ulrar
  • 895
  • 8
  • 17

1 Answers1

3

From what I can tell, the second argument of Lwt_io.write_from_exactly is of type bytes (a mutable OCaml string), whereas a Cstruct.buffer is a Bigarray of 8-bit integers. While the underlying "payloads" are the same (word-aligned arrays of unsigned chars; see the Bytes_val macro), the "value wrappers" at the OCaml level are different (see, for example, caml_ba_alloc).

Have you tried using Lwt_bytes.to_bytes to convert from one to the other?

Unfortunately, this seems to duplicate and copy the data payload, so it may be better to rethink your overall approach. There's not enough information in your question to make a more precise suggestion.

tbrk
  • 1,290
  • 1
  • 13
  • 20
  • 2
    This answer is correct. To elaborate a bit, `Lwt_bytes.t`s *are* bigarrays compatible with Cstruct, but `bytes` is a core OCaml type, the type of mutable strings. The naming is confusing, so it's easy to think that `bytes` = `Lwt_bytes.t`. The reason for this is that `Lwt_bytes` was given its name long before `bytes` was added as a new type to the core language. `Lwt_io` is built over `bytes`, i.e. regular (mutable) OCaml strings. To do I/O with `Lwt_bytes.t`, it's necessary to use the functions in module `Lwt_bytes` (or other bigarray libraries). – antron Oct 14 '18 at 17:08
  • 2
    I also want to note that asynchronous I/O with `string`s or `bytes` (like in `Lwt_io`) is almost always less efficient that I/O with bigstrings (like Cstruct, `Lwt_bytes`). This is because `string` and `bytes` storage is managed by the garbage collector, and can be moved, so Lwt (or any other I/O lib) has to do an internal copy, so the address of the data remains fixed for the duration of the I/O. Bigstrings (`Lwt_bytes.t`, Cstruct) are inherently allocated with fixed storage, so I/O requires no copying. The `Lwt_bytes` API is not (currently) as rich as `Lwt_io`, however. – antron Oct 14 '18 at 17:11
  • 1
    I understand, I had indeed not realized Lwt_bytes.t and bytes weren't the same. It makes a lot more sense now, and using bytes does work fine. Since I am using Lwt_io, I just replaced cstruct with bytes – Ulrar Oct 14 '18 at 17:19