rust-lang / rust-lang/rust-bindgen

request: clear instructions on how to handle cpp layout failures

Open
#1,262 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement help wanted I-needs-docs
Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Input C/C++ Header

Im attempting to generate bindings for the cpp api for apache arrow. The header file links to a number of other headers, which is difficult to include here.

Bindgen Invocation

(ignore the raw absolute paths)

extern crate bindgen;

use std::env;
use std::path::PathBuf;

fn main() {
    println!("cargo:rustc-env=LD_LIBRARY_PATH={}", "/Users/crawford/git/rust/arrow-sys/arrow/cpp/debug/debug/");
    let base = "/Users/crawford/git/rust/arrow-sys/arrow/cpp/src";

    let bindings = bindgen::Builder::default()
        .opaque_type("std::.*")
        .whitelist_type("arrow::.*")
        .enable_cxx_namespaces()
        .clang_arg("-xc++") // change to cpp mode
        .clang_arg("-std=c++14")
        .clang_arg(format!("-I{}", base))
        .header(format!("{}/arrow/api.h", base))
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}
Actual Results

I successfully generated the bindings, but a number of the layout tests fail. I included a snippet of the failures below. The problem is:

  • the bindgen docs dont make clear what the impact of incorrect layout is
  • if I avoid using these types, will the bindings still work?
  • where is the true size (eg, 40 in the below) from?
  • what steps should I take to correct this
    • for instance, what is a likely cause for layout issues
---- root::arrow::bindgen_test_layout_UInt64Type stdout ----
        thread 'root::arrow::bindgen_test_layout_UInt64Type' panicked at 'assertion failed: `(left == right)`
  left: `48`,
 right: `40`: Size of: UInt64Type', /Users/crawford/git/rust/arrow-sys/target/debug/build/arrow-sys-903815425d802955/out/bindings.rs:2541:13

---- root::arrow::bindgen_test_layout_UInt8Type stdout ----
        thread 'root::arrow::bindgen_test_layout_UInt8Type' panicked at 'assertion failed: `(left == right)`
  left: `48`,
 right: `40`: Size of: UInt8Type', /Users/crawford/git/rust/arrow-sys/target/debug/build/arrow-sys-903815425d802955/out/bindings.rs:2415:13


failures:
    root::__bindgen_test_layout_DictionaryBuilder_open0_BinaryType_close0_instantiation
    root::__bindgen_test_layout_DictionaryBuilder_open0_StringType_close0_instantiation
    root::arrow::__bindgen_test_layout_DictionaryBuilder_open0_NullType_close0_instantiation
    root::arrow::bindgen_test_layout_BinaryDictionaryBuilder
    root::arrow::bindgen_test_layout_DecimalType
    root::arrow::bindgen_test_layout_DoubleType
    root::arrow::bindgen_test_layout_FloatType
    root::arrow::bindgen_test_layout_HalfFloatType
    root::arrow::bindgen_test_layout_Int16Type
    root::arrow::bindgen_test_layout_Int32Type
    root::arrow::bindgen_test_layout_Int64Type
    root::arrow::bindgen_test_layout_Int8Type
    root::arrow::bindgen_test_layout_StringDictionaryBuilder
    root::arrow::bindgen_test_layout_UInt16Type
    root::arrow::bindgen_test_layout_UInt32Type
    root::arrow::bindgen_test_layout_UInt64Type
    root::arrow::bindgen_test_layout_UInt8Type

test result: FAILED. 150 passed; 17 failed; 0 ignored; 0 measured; 0 filtered out

A snippet for a failing type (size should be 40 (according to the test), but we have 8 from the vtable + 40 from the _base arrow):

        #[repr(C)]
        pub struct UInt8Type__bindgen_vtable(::std::os::raw::c_void);
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct UInt8Type {
            pub vtable_: *const UInt8Type__bindgen_vtable,
            pub _base: [u64; 5usize],
        }
        #[test]
        fn bindgen_test_layout_UInt8Type() {
            assert_eq!(
                ::std::mem::size_of::<UInt8Type>(),
                40usize,
                concat!("Size of: ", stringify!(UInt8Type))
            );
            assert_eq!(
                ::std::mem::align_of::<UInt8Type>(),
                8usize,
                concat!("Alignment of ", stringify!(UInt8Type))
            );
        }
Expected Results

All the layout tests pass, or a chapter in the bindgen book on why they might not pass for cpp code.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated bindings.rs layout tests, including bindgen_test_layout_UInt8Type and the listed failing types, and compare their reported Rust sizes with the expected values. Trace the bindgen invocation and the generated vtable and _base fields shown in the issue. Done means adding a bindgen book chapter that explains layout-test failures, their impact on C++ bindings, the source of expected sizes, likely causes, and corrective steps.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
compilers, devtools
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.