rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Functions that use vtables get `improper_ctypes` warning

Open tgross35 opened this issue 2 years ago • 0 comments

Input C/C++ Header

struct TABLE
{
  TABLE() = default;

  TABLE_SHARE	*s;
  handler	*file;
  TABLE *next, *prev;
  // ... it's a very long class, I can provide more information if needed
}

Bindgen Invocation

    bindgen::Builder::default()
        // The input header we would like to generate
        // bindings for.
        .header("src/wrapper.h")
        // Fix math.h double defines
        .parse_callbacks(Box::new(BuildCallbacks))
        .clang_args(incl_args)
        .clang_arg("-xc++")
        .clang_arg("-std=c++17")
        // Don't derive copy for structs
        .derive_copy(false)
        // Use `core::ffi` instead of `std::os::raw`
        .use_core()
        // Will be required in a future version of `rustc`
        .wrap_unsafe_ops(true)
        // Use rust-style enums labeled with non_exhaustive to represent C enums
        .default_enum_style(EnumVariation::Rust {
            non_exhaustive: true,
        })
        .vtable_generation(true)
        .allowlist_item(...)
        .generate()
        .map_err(Into::into)

Actual Results

warning: `extern` block uses type `Handler_share__bindgen_vtable`, which is not FFI-safe
     --> /Users/tmgross/Documents/projects/mdb/mariadb-server/rust/target/debug/build/mariadb-sys-b864f0925472491e/out/bindings.rs:27016:16
      |
27016 |         table: *mut TABLE,
      |                ^^^^^^^^^^ not FFI-safe
      |
      = help: consider adding a member to this struct
      = note: this struct has no fields
note: the type is defined here
     --> /Users/tmgross/Documents/projects/mdb/mariadb-server/rust/target/debug/build/mariadb-sys-b864f0925472491e/out/bindings.rs:19773:1
      |
19773 | pub struct Handler_share__bindgen_vtable {}

This comes from the following:

#[repr(C)]
pub struct Handler_share__bindgen_vtable {}
#[doc = " Base class to be used by handlers different shares"]
#[repr(C)]
#[derive(Debug)]
pub struct Handler_share {
    pub vtable_: *const Handler_share__bindgen_vtable,
}

// Omitting a few levels of indirection through which a `struct TABLE` contains
// a `*mut *mut Handler_share`, can provide if needed.

extern "C" {
    #[link_name = "\u{1}__ZN19TABLE_STATISTICS_CB21update_stats_in_tableEP5TABLE"]
    pub fn TABLE_STATISTICS_CB_update_stats_in_table(
        this: *mut TABLE_STATISTICS_CB,
        table: *mut TABLE,
    );
}

Expected Results

There shouldn't be a warning.

I think this could be worked around by adding the [u8; 0] value to the struct, or maybe c_void. Otherwise, adding #[allow(improper_ctypes)] to the calling function would work.

tgross35 avatar Dec 20 '23 17:12 tgross35