On Mon, Aug 14, 2023 at 07:55:15AM +0000, Tage Johansson wrote:
> 
> 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-optimization>
> 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.

Ah, so if I'm understanding correctly, even though the libnbd API
requires a non-NULL function pointer, the problem is that the FFI code
can't in general tell which C functions with a function pointer
parameter allow NULL and which do not, so the conservative approach is
to document that _all_ FFI interactions with C functions use an
Option<T> nullable pointer when passing a function pointer across the
Rust->C boundary.  It looks odd in relation to the libnbd
documentation of requiring non-NULL function, but is well-hidden
inside our internal code, and does not leak out to the public Rust
interface.  That fills in some gaps for me; thanks.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to