On 8/11/2023 2:00 PM, Eric Blake wrote:
On Thu, Aug 03, 2023 at 03:36:05PM +0000, Tage Johansson wrote:
> This commit creates basic Rust bindings in the rust directory.
> The bindings are generated by generator/Rust.ml and
> generator/RustSys.ml.
> ---
> --- /dev/null
> +++ b/generator/RustSys.ml
> +(** Print the struct for a closure. *)
> +let print_closure_struct { cbname; cbargs } =
> + pr "#[repr(C)]\n";
> + pr "#[derive(Debug, Clone, Copy)]\n";
> + pr "pub struct nbd_%s_callback {\n" cbname;
> + pr " pub callback: \n";
> + pr " Option<unsafe extern \"C\" fn(*mut c_void, %s) ->
c_int>,\n"
> + (cbargs |> List.map cbarg_types |> List.flatten |> String.concat
", ");
> + pr " pub user_data: *mut c_void,\n";
> + pr " pub free: Option<unsafe extern \"C\" fn(*mut
c_void)>,\n";
> + pr "}\n"
Why is 'callback' an Option<> rather than a mandatory argument? I get
that 'free' must be an Option<> (because it corresponds to an
OClosure, which is an optional callback), but 'callback' is a
mandatory function pointer in the C API; why would it ever be
acceptable to pass None instead of Some<function>?
It uses the "nullable pointer optimization"
<
https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimizat...
which makes an Option<T> where T is a non nullable type be represented
with no extra space, and the None variant is represented by NULL.
Keep in mind that this is only the internal FFI bindings and the Option
will never be part of the public interface.
Best regards,
Tage