  let dec_ref =
    let f =
      foreign ~from:c_lib "${capi.get_name("dec_ref_unit_provider")}"
        (c_type @-> raisable void)
    in
    (fun v ->
      f (!@ v))

  (* Keep is a special argument designed to extend the lifetime of an OCaml
     value. We put in a ref which is set to [None] only in the finalization
     function. This guarantees it won't be collected before. *)
  let wrap ?keep v =
    let ref_keep = ref keep in
    let finalise arg =
      ref_keep := None;
      dec_ref arg
    in
    allocate ~finalise (ptr void) v

  let create_auto_provider =
    foreign ~from:c_lib "${capi.get_name("create_auto_provider")}"
      (ptr (ptr char) @-> string @-> raisable c_type)

  let auto input_files =
    (* Convert the names of the input files into pointers to C strings. We used
       to use the high-level type [Ctypes.string] type, but this was causing
       memory corruption problems. We switched to [ptr char] instead. *)
    let cstrings =
      List.map (fun f -> CArray.(start (of_string f))) input_files
    in
    (* Add a null pointer at the end. This is part of the LAL calling
       convention. *)
    let null_ptr = from_voidp char Ctypes.null in
    let cstrings_null = List.rev_append cstrings [null_ptr] in
    (* Create an array with all these pointers *)
    let array = CArray.of_list (ptr char) cstrings_null in
    let ptr = CArray.start array in
    let result = create_auto_provider ptr "" in
    (* Extend the lifetime of cstrings here, to make sure it is not garbage
       collected while [create_auto_provided] executes, nor after. (It is not
       clear whether LAL keeps internal references to this C object after the
       call to create_auto_provider, but simpler fixes do not work anyway. *)
    wrap ~keep:cstrings result
