Out parameters in ctypes?

I’m probably missing something obvious here, but how do you do out parameters in ctypes?

In particular, I’m trying to wrap iconv:


The naive signature would be something like:

let iconv' =
    @-> ptr string
    @-> ptr size_t
    @-> ptr (ptr char)
    @-> ptr size_t
    @-> returning size_t)

But using this is incredibly awkward since I need to allocate copies of every parameter:

let iconv t input =
  let in_bytes_left = allocate size_t (String.length input |> Unsigned.Size_t.of_int) in
  let out_size = String.length input * 2 in
  let out_bytes_left = allocate size_t (Unsigned.Size_t.of_int out_size) in
  let in_buf = allocate string input in
  let out_buf = allocate_n char ~count:out_size in
  let out_buf_ptr = allocate (ptr char) out_buf in
  let res =
    iconv' t in_buf in_bytes_left out_buf_ptr out_bytes_left |> Unsigned.Size_t.to_int
  assert (res = 0);
  assert (!@in_bytes_left = Unsigned.Size_t.of_int 0);
  assert (!@out_bytes_left > Unsigned.Size_t.of_int 0);
  let converted = string_from_ptr ~length:out_size out_buf in
  String.sub converted 0 (out_size - Unsigned.Size_t.to_int !@out_bytes_left)

Is there any way I can just pass references to my int and byte params instead of having to do this? I assume for the string param I would need to use ocaml_string, but even with that, I can’t figure out how to take a reference to it.