I’m probably missing something obvious here, but how do you do out parameters in ctypes?
In particular, I’m trying to wrap iconv
:
https://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.15/iconv.3.html
The naive signature would be something like:
let iconv' =
foreign
"iconv"
~check_errno:true
(iconv_t
@-> 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
in
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.