rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.23k stars 679 forks source link

How to construct the std::string variable in the generated rust #2768

Closed aohanhe closed 3 months ago

aohanhe commented 4 months ago

c++ code

#include` <string>
using namespace std;

string hello(string name){
    return "你好啊!"+name;
}

build.rs

use std::{env, path::PathBuf};

fn main() {
    println!("cargo:rustc-link-search=native={}", "./testcpp/build");
    println!("cargo:rustc-link-lib=static=testcpp");

    let bindings = bindgen::Builder::default()
        .enable_cxx_namespaces()               
        .wrap_unsafe_ops(true)
        .header("wrapper.h")        
        .clang_arg("-x")
        .clang_arg("c++")
        .clang_arg("--std=c++14")        
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .allowlist_file(r"^(/usr/local/include/.*/.*.h)$")        
        .generate()
        .expect("无法正常生成binding");

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

bindings.rs

/* automatically generated by rust-bindgen 0.69.4 */

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[repr(C)]
    #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
    pub struct __BindgenBitfieldUnit<Storage> {
        storage: Storage,
    }
    impl<Storage> __BindgenBitfieldUnit<Storage> {
        #[inline]
        pub const fn new(storage: Storage) -> Self {
            Self { storage }
        }
    }
    impl<Storage> __BindgenBitfieldUnit<Storage>
    where
        Storage: AsRef<[u8]> + AsMut<[u8]>,
    {
        #[inline]
        pub fn get_bit(&self, index: usize) -> bool {
            debug_assert!(index / 8 < self.storage.as_ref().len());
            let byte_index = index / 8;
            let byte = self.storage.as_ref()[byte_index];
            let bit_index = if cfg!(target_endian = "big") {
                7 - (index % 8)
            } else {
                index % 8
            };
            let mask = 1 << bit_index;
            byte & mask == mask
        }
        #[inline]
        pub fn set_bit(&mut self, index: usize, val: bool) {
            debug_assert!(index / 8 < self.storage.as_ref().len());
            let byte_index = index / 8;
            let byte = &mut self.storage.as_mut()[byte_index];
            let bit_index = if cfg!(target_endian = "big") {
                7 - (index % 8)
            } else {
                index % 8
            };
            let mask = 1 << bit_index;
            if val {
                *byte |= mask;
            } else {
                *byte &= !mask;
            }
        }
        #[inline]
        pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
            debug_assert!(bit_width <= 64);
            debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
            debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
            let mut val = 0;
            for i in 0..(bit_width as usize) {
                if self.get_bit(i + bit_offset) {
                    let index = if cfg!(target_endian = "big") {
                        bit_width as usize - 1 - i
                    } else {
                        i
                    };
                    val |= 1 << index;
                }
            }
            val
        }
        #[inline]
        pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
            debug_assert!(bit_width <= 64);
            debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
            debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
            for i in 0..(bit_width as usize) {
                let mask = 1 << i;
                let val_bit_is_set = val & mask == mask;
                let index = if cfg!(target_endian = "big") {
                    bit_width as usize - 1 - i
                } else {
                    i
                };
                self.set_bit(index + bit_offset, val_bit_is_set);
            }
        }
    }
    #[repr(C)]
    pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
    impl<T> __BindgenUnionField<T> {
        #[inline]
        pub const fn new() -> Self {
            __BindgenUnionField(::std::marker::PhantomData)
        }
        #[inline]
        pub unsafe fn as_ref(&self) -> &T {
            unsafe { ::std::mem::transmute(self) }
        }
        #[inline]
        pub unsafe fn as_mut(&mut self) -> &mut T {
            unsafe { ::std::mem::transmute(self) }
        }
    }
    impl<T> ::std::default::Default for __BindgenUnionField<T> {
        #[inline]
        fn default() -> Self {
            Self::new()
        }
    }
    impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
        #[inline]
        fn clone(&self) -> Self {
            *self
        }
    }
    impl<T> ::std::marker::Copy for __BindgenUnionField<T> {}
    impl<T> ::std::fmt::Debug for __BindgenUnionField<T> {
        fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
            fmt.write_str("__BindgenUnionField")
        }
    }
    impl<T> ::std::hash::Hash for __BindgenUnionField<T> {
        fn hash<H: ::std::hash::Hasher>(&self, _state: &mut H) {}
    }
    impl<T> ::std::cmp::PartialEq for __BindgenUnionField<T> {
        fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
            true
        }
    }
    impl<T> ::std::cmp::Eq for __BindgenUnionField<T> {}
    #[allow(unused_imports)]
    use self::super::root;
    pub mod std {
        #[allow(unused_imports)]
        use self::super::super::root;
        pub type integral_constant_value_type<_Tp> = _Tp;
        pub type integral_constant_type = u8;
        pub type true_type = u8;
        pub type _If = u8;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct iterator_traits {
            pub _address: u8,
        }
        pub type iterator_traits___primary_template = root::std::iterator_traits;
        pub type string = root::std::basic_string;
        pub type streampos = root::std::fpos<root::__mbstate_t>;
        pub type streamoff = ::std::os::raw::c_longlong;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct fpos<_StateT> {
            pub __st_: _StateT,
            pub __off_: root::std::streamoff,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_StateT>>,
        }
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct iterator {
            pub _address: u8,
        }
        pub type iterator_value_type<_Tp> = _Tp;
        pub type iterator_difference_type<_Distance> = _Distance;
        pub type iterator_pointer<_Pointer> = _Pointer;
        pub type iterator_reference<_Reference> = _Reference;
        pub type iterator_iterator_category<_Category> = _Category;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct reverse_iterator<_Iter> {
            pub __t_: _Iter,
            pub current: _Iter,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_Iter>>,
        }
        pub type reverse_iterator_iterator_type<_Iter> = _Iter;
        pub type reverse_iterator_iterator_category = root::std::_If;
        pub type reverse_iterator_pointer = root::std::iterator_traits;
        pub type reverse_iterator_value_type = root::std::iterator_traits;
        pub type reverse_iterator_difference_type = root::std::iterator_traits;
        pub type reverse_iterator_reference = root::std::iterator_traits;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct __wrap_iter<_Iter> {
            pub __i_: root::std::__wrap_iter_iterator_type<_Iter>,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_Iter>>,
        }
        pub type __wrap_iter_iterator_type<_Iter> = _Iter;
        pub type __wrap_iter_value_type = root::std::iterator_traits;
        pub type __wrap_iter_difference_type = root::std::iterator_traits;
        pub type __wrap_iter_pointer = root::std::iterator_traits;
        pub type __wrap_iter_reference = root::std::iterator_traits;
        pub type __wrap_iter_iterator_category = root::std::iterator_traits;
        pub type __allocator_traits_rebind_type = [u8; 0usize];
        pub type __allocator_traits_rebind_t = u8;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct allocator_traits {
            pub _address: u8,
        }
        pub type allocator_traits_allocator_type<_Alloc> = _Alloc;
        pub type allocator_traits_value_type = [u8; 0usize];
        pub type allocator_traits_pointer = [u8; 0usize];
        pub type allocator_traits_const_pointer = [u8; 0usize];
        pub type allocator_traits_void_pointer = [u8; 0usize];
        pub type allocator_traits_const_void_pointer = [u8; 0usize];
        pub type allocator_traits_difference_type = [u8; 0usize];
        pub type allocator_traits_size_type = [u8; 0usize];
        pub type allocator_traits_propagate_on_container_copy_assignment = u8;
        pub type allocator_traits_propagate_on_container_move_assignment = u8;
        pub type allocator_traits_propagate_on_container_swap = u8;
        pub type allocator_traits_is_always_equal = u8;
        pub type allocator_traits_rebind_alloc = root::std::__allocator_traits_rebind_t;
        pub type allocator_traits_rebind_traits = root::std::allocator_traits;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct allocator {
            pub _address: u8,
        }
        pub type allocator_size_type = ::std::os::raw::c_ulong;
        pub type allocator_difference_type = ::std::os::raw::c_long;
        pub type allocator_value_type<_Tp> = _Tp;
        pub type allocator_propagate_on_container_move_assignment = root::std::true_type;
        pub type allocator_is_always_equal = root::std::true_type;
        pub type allocator_pointer<_Tp> = *mut _Tp;
        pub type allocator_const_pointer<_Tp> = *const _Tp;
        pub type allocator_reference<_Tp> = *mut _Tp;
        pub type allocator_const_reference<_Tp> = *const _Tp;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct allocator_rebind {
            pub _address: u8,
        }
        pub type allocator_rebind_other = root::std::allocator;
        pub type __compressed_pair_elem__ParamT<_Tp> = _Tp;
        pub type __compressed_pair_elem_reference<_Tp> = *mut _Tp;
        pub type __compressed_pair_elem_const_reference<_Tp> = *const _Tp;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct __compressed_pair {
            pub _address: u8,
        }
        pub type __compressed_pair__Base1 = u8;
        pub type __compressed_pair__Base2 = u8;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct char_traits {
            pub _address: u8,
        }
        pub type char_traits_char_type<_CharT> = _CharT;
        pub type char_traits_int_type = ::std::os::raw::c_int;
        pub type char_traits_off_type = root::std::streamoff;
        pub type char_traits_pos_type = root::std::streampos;
        pub type char_traits_state_type = root::__mbstate_t;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string_view<_CharT> {
            pub __data_: *const root::std::basic_string_view_value_type<_CharT>,
            pub __size_: root::std::basic_string_view_size_type,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_CharT>>,
        }
        pub type basic_string_view_traits_type<_Traits> = _Traits;
        pub type basic_string_view_value_type<_CharT> = _CharT;
        pub type basic_string_view_pointer<_CharT> = *mut _CharT;
        pub type basic_string_view_const_pointer<_CharT> = *const _CharT;
        pub type basic_string_view_reference<_CharT> = *mut _CharT;
        pub type basic_string_view_const_reference<_CharT> = *const _CharT;
        pub type basic_string_view_const_iterator<_CharT> =
            root::std::basic_string_view_const_pointer<_CharT>;
        pub type basic_string_view_iterator<_CharT> =
            root::std::basic_string_view_const_iterator<_CharT>;
        pub type basic_string_view_const_reverse_iterator<_CharT> =
            root::std::reverse_iterator<root::std::basic_string_view_const_iterator<_CharT>>;
        pub type basic_string_view_reverse_iterator<_CharT> =
            root::std::basic_string_view_const_reverse_iterator<_CharT>;
        pub type basic_string_view_size_type = ::std::os::raw::c_ulong;
        pub type basic_string_view_difference_type = ::std::os::raw::c_long;
        pub mod __fs {
            #[allow(unused_imports)]
            use self::super::super::super::root;
        }
        #[repr(C)]
        pub struct basic_string {
            pub __r_: root::std::__compressed_pair,
        }
        pub type basic_string___self = root::std::basic_string;
        pub type basic_string___self_view<_CharT> = root::std::basic_string_view<_CharT>;
        pub type basic_string_traits_type<_Traits> = _Traits;
        pub type basic_string_value_type<_CharT> = _CharT;
        pub type basic_string_allocator_type<_Allocator> = _Allocator;
        pub type basic_string___alloc_traits = root::std::allocator_traits;
        pub type basic_string_size_type = root::std::basic_string___alloc_traits;
        pub type basic_string_difference_type = root::std::basic_string___alloc_traits;
        pub type basic_string_reference<_CharT> = *mut root::std::basic_string_value_type<_CharT>;
        pub type basic_string_const_reference<_CharT> =
            *const root::std::basic_string_value_type<_CharT>;
        pub type basic_string_pointer = root::std::basic_string___alloc_traits;
        pub type basic_string_const_pointer = root::std::basic_string___alloc_traits;
        pub type basic_string_iterator = root::std::__wrap_iter<root::std::basic_string_pointer>;
        pub type basic_string_const_iterator =
            root::std::__wrap_iter<root::std::basic_string_const_pointer>;
        pub type basic_string_reverse_iterator =
            root::std::reverse_iterator<root::std::basic_string_iterator>;
        pub type basic_string_const_reverse_iterator =
            root::std::reverse_iterator<root::std::basic_string_const_iterator>;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string___long {
            pub __bindgen_anon_1: u8,
            pub __size_: root::std::basic_string_size_type,
            pub __data_: root::std::basic_string_pointer,
        }
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string___long__bindgen_ty_1 {
            pub _address: u8,
        }
        pub const basic_string___min_cap: root::std::basic_string__bindgen_ty_1 = 0;
        pub type basic_string__bindgen_ty_1 = i32;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string___short<_CharT> {
            pub __bindgen_anon_1: root::std::basic_string___short__bindgen_ty_1,
            pub __padding_: *mut ::std::os::raw::c_char,
            pub __data_: *mut root::std::basic_string_value_type<_CharT>,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_CharT>>,
        }
        #[repr(C, packed)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string___short__bindgen_ty_1 {
            pub _bitfield_align_1: [u8; 0],
            pub _bitfield_1: root::__BindgenBitfieldUnit<[u8; 1usize]>,
        }
        impl basic_string___short__bindgen_ty_1 {
            #[inline]
            pub fn __is_long_(&self) -> ::std::os::raw::c_uchar {
                unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
            }
            #[inline]
            pub fn set___is_long_(&mut self, val: ::std::os::raw::c_uchar) {
                unsafe {
                    let val: u8 = ::std::mem::transmute(val);
                    self._bitfield_1.set(0usize, 1u8, val as u64)
                }
            }
            #[inline]
            pub fn __size_(&self) -> ::std::os::raw::c_uchar {
                unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 7u8) as u8) }
            }
            #[inline]
            pub fn set___size_(&mut self, val: ::std::os::raw::c_uchar) {
                unsafe {
                    let val: u8 = ::std::mem::transmute(val);
                    self._bitfield_1.set(1usize, 7u8, val as u64)
                }
            }
            #[inline]
            pub fn new_bitfield_1(
                __is_long_: ::std::os::raw::c_uchar,
                __size_: ::std::os::raw::c_uchar,
            ) -> root::__BindgenBitfieldUnit<[u8; 1usize]> {
                let mut __bindgen_bitfield_unit: root::__BindgenBitfieldUnit<[u8; 1usize]> =
                    Default::default();
                __bindgen_bitfield_unit.set(0usize, 1u8, {
                    let __is_long_: u8 = unsafe { ::std::mem::transmute(__is_long_) };
                    __is_long_ as u64
                });
                __bindgen_bitfield_unit.set(1usize, 7u8, {
                    let __size_: u8 = unsafe { ::std::mem::transmute(__size_) };
                    __size_ as u64
                });
                __bindgen_bitfield_unit
            }
        }
        #[repr(C)]
        #[repr(align(1))]
        pub struct basic_string___ulx<_CharT> {
            pub __lx: root::__BindgenUnionField<root::std::basic_string___long>,
            pub __lxx: root::__BindgenUnionField<root::std::basic_string___short<_CharT>>,
            pub bindgen_union_field: [u8; 0usize],
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_CharT>>,
        }
        pub const basic_string___n_words: root::std::basic_string__bindgen_ty_2 = 0;
        pub type basic_string__bindgen_ty_2 = i32;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct basic_string___raw {
            pub __words: *mut root::std::basic_string_size_type,
        }
        #[repr(C)]
        pub struct basic_string___rep<_CharT> {
            pub __bindgen_anon_1: root::std::basic_string___rep__bindgen_ty_1<_CharT>,
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_CharT>>,
        }
        #[repr(C)]
        #[repr(align(1))]
        pub struct basic_string___rep__bindgen_ty_1<_CharT> {
            pub __l: root::__BindgenUnionField<root::std::basic_string___long>,
            pub __s: root::__BindgenUnionField<root::std::basic_string___short<_CharT>>,
            pub __r: root::__BindgenUnionField<root::std::basic_string___raw>,
            pub bindgen_union_field: [u8; 0usize],
            pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<_CharT>>,
        }
        pub const basic_string___alignment: root::std::basic_string__bindgen_ty_3 = 0;
        pub type basic_string__bindgen_ty_3 = i32;
    }
    #[repr(C)]
    #[derive(Copy, Clone)]
    pub union __mbstate_t {
        pub __mbstate8: [::std::os::raw::c_char; 128usize],
        pub _mbstateL: ::std::os::raw::c_longlong,
    }
    #[test]
    fn bindgen_test_layout___mbstate_t() {
        const UNINIT: ::std::mem::MaybeUninit<__mbstate_t> = ::std::mem::MaybeUninit::uninit();
        let ptr = UNINIT.as_ptr();
        assert_eq!(
            ::std::mem::size_of::<__mbstate_t>(),
            128usize,
            concat!("Size of: ", stringify!(__mbstate_t))
        );
        assert_eq!(
            ::std::mem::align_of::<__mbstate_t>(),
            8usize,
            concat!("Alignment of ", stringify!(__mbstate_t))
        );
        assert_eq!(
            unsafe { ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize },
            0usize,
            concat!(
                "Offset of field: ",
                stringify!(__mbstate_t),
                "::",
                stringify!(__mbstate8)
            )
        );
        assert_eq!(
            unsafe { ::std::ptr::addr_of!((*ptr)._mbstateL) as usize - ptr as usize },
            0usize,
            concat!(
                "Offset of field: ",
                stringify!(__mbstate_t),
                "::",
                stringify!(_mbstateL)
            )
        );
    }
    extern "C" {
        #[link_name = "\u{1}__Z5helloNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE"]
        pub fn hello(name: root::std::string) -> root::std::string;
    }
    #[test]
    fn __bindgen_test_layout_basic_string_open0_char_char_traits_open1_char_close1_allocator_open1_char_close1_close0_instantiation(
    ) {
        assert_eq!(
            ::std::mem::size_of::<root::std::basic_string>(),
            24usize,
            concat!(
                "Size of template specialization: ",
                stringify!(root::std::basic_string)
            )
        );
        assert_eq!(
            ::std::mem::align_of::<root::std::basic_string>(),
            8usize,
            concat!(
                "Alignment of template specialization: ",
                stringify!(root::std::basic_string)
            )
        );
    }
    #[test]
    fn __bindgen_test_layout_char_traits_open0_char_close0_instantiation() {
        assert_eq!(
            ::std::mem::size_of::<root::std::char_traits>(),
            1usize,
            concat!(
                "Size of template specialization: ",
                stringify!(root::std::char_traits)
            )
        );
        assert_eq!(
            ::std::mem::align_of::<root::std::char_traits>(),
            1usize,
            concat!(
                "Alignment of template specialization: ",
                stringify!(root::std::char_traits)
            )
        );
    }
    #[test]
    fn __bindgen_test_layout_allocator_open0_char_close0_instantiation() {
        assert_eq!(
            ::std::mem::size_of::<root::std::allocator>(),
            1usize,
            concat!(
                "Size of template specialization: ",
                stringify!(root::std::allocator)
            )
        );
        assert_eq!(
            ::std::mem::align_of::<root::std::allocator>(),
            1usize,
            concat!(
                "Alignment of template specialization: ",
                stringify!(root::std::allocator)
            )
        );
    }
}

The problem I ran into was how do I instantiate this root::std:string? thanks

GKFX commented 3 months ago

Working with std::string in Rust is apparently quite awkward as it has a move constructor. The cxx crate is designed to provide access to C++ standard library types in Rust and vice versa for FFI - see https://cxx.rs/binding/cxxstring.html.

emilio commented 3 months ago

Yeah, it's really not properly supported by bindgen since it has interior pointers, and the implementation is not public anyways, so anything you do kinda would need to call into custom C++ code, which is out of scope for bindgen. autocxx also does something like that on top of bindgen iirc?