Merge branch 'fix/valist-abi' into 'master'
libvlc-sys: fix cross-platform va_list layout See merge request videolan/vlc-rs!20merge-requests/20/merge
commit
1fbb2376ba
|
|
@ -1,145 +1,7 @@
|
|||
/* automatically generated by rust-bindgen 0.72.1 */
|
||||
|
||||
#[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]
|
||||
fn extract_bit(byte: u8, index: usize) -> bool {
|
||||
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 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];
|
||||
Self::extract_bit(byte, index)
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool {
|
||||
debug_assert!(index / 8 < core::mem::size_of::<Storage>());
|
||||
let byte_index = index / 8;
|
||||
let byte = unsafe {
|
||||
*(core::ptr::addr_of!((*this).storage) as *const u8).offset(byte_index as isize)
|
||||
};
|
||||
Self::extract_bit(byte, index)
|
||||
}
|
||||
#[inline]
|
||||
fn change_bit(byte: u8, index: usize, val: bool) -> u8 {
|
||||
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 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];
|
||||
*byte = Self::change_bit(*byte, index, val);
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) {
|
||||
debug_assert!(index / 8 < core::mem::size_of::<Storage>());
|
||||
let byte_index = index / 8;
|
||||
let byte = unsafe {
|
||||
(core::ptr::addr_of_mut!((*this).storage) as *mut u8).offset(byte_index as isize)
|
||||
};
|
||||
unsafe { *byte = Self::change_bit(*byte, index, val) };
|
||||
}
|
||||
#[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 unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 {
|
||||
debug_assert!(bit_width <= 64);
|
||||
debug_assert!(bit_offset / 8 < core::mem::size_of::<Storage>());
|
||||
debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::<Storage>());
|
||||
let mut val = 0;
|
||||
for i in 0..(bit_width as usize) {
|
||||
if unsafe { Self::raw_get_bit(this, 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);
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) {
|
||||
debug_assert!(bit_width <= 64);
|
||||
debug_assert!(bit_offset / 8 < core::mem::size_of::<Storage>());
|
||||
debug_assert!((bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::<Storage>());
|
||||
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
|
||||
};
|
||||
unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) };
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use crate::valist::VaList;
|
||||
|
||||
pub const VLC_VLC_H: u32 = 1;
|
||||
pub const VLC_LIBVLC_H: u32 = 1;
|
||||
pub const VLC_LIBVLC_RENDERER_DISCOVERER_H: u32 = 1;
|
||||
|
|
@ -155,8 +17,6 @@ pub const LIBVLC_EVENTS_H: u32 = 1;
|
|||
pub const LIBVLC_DIALOG_H: u32 = 1;
|
||||
pub const LIBVLC_VLM_H: u32 = 1;
|
||||
pub const LIBVLC_DEPRECATED_H: u32 = 1;
|
||||
pub type __gnuc_va_list = __builtin_va_list;
|
||||
pub type __uint64_t = libc::c_ulong;
|
||||
pub type __off_t = libc::c_long;
|
||||
pub type __off64_t = libc::c_long;
|
||||
pub type FILE = _IO_FILE;
|
||||
|
|
@ -194,9 +54,7 @@ pub struct _IO_FILE {
|
|||
pub _markers: *mut _IO_marker,
|
||||
pub _chain: *mut _IO_FILE,
|
||||
pub _fileno: libc::c_int,
|
||||
pub _bitfield_align_1: [u32; 0],
|
||||
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>,
|
||||
pub _short_backupbuf: [libc::c_char; 1usize],
|
||||
pub _flags2: libc::c_int,
|
||||
pub _old_offset: __off_t,
|
||||
pub _cur_column: libc::c_ushort,
|
||||
pub _vtable_offset: libc::c_schar,
|
||||
|
|
@ -207,11 +65,9 @@ pub struct _IO_FILE {
|
|||
pub _wide_data: *mut _IO_wide_data,
|
||||
pub _freeres_list: *mut _IO_FILE,
|
||||
pub _freeres_buf: *mut libc::c_void,
|
||||
pub _prevchain: *mut *mut _IO_FILE,
|
||||
pub __pad5: usize,
|
||||
pub _mode: libc::c_int,
|
||||
pub _unused3: libc::c_int,
|
||||
pub _total_written: __uint64_t,
|
||||
pub _unused2: [libc::c_char; 8usize],
|
||||
pub _unused2: [libc::c_char; 20usize],
|
||||
}
|
||||
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
|
||||
const _: () = {
|
||||
|
|
@ -243,8 +99,7 @@ const _: () = {
|
|||
["Offset of field: _IO_FILE::_markers"][::core::mem::offset_of!(_IO_FILE, _markers) - 96usize];
|
||||
["Offset of field: _IO_FILE::_chain"][::core::mem::offset_of!(_IO_FILE, _chain) - 104usize];
|
||||
["Offset of field: _IO_FILE::_fileno"][::core::mem::offset_of!(_IO_FILE, _fileno) - 112usize];
|
||||
["Offset of field: _IO_FILE::_short_backupbuf"]
|
||||
[::core::mem::offset_of!(_IO_FILE, _short_backupbuf) - 119usize];
|
||||
["Offset of field: _IO_FILE::_flags2"][::core::mem::offset_of!(_IO_FILE, _flags2) - 116usize];
|
||||
["Offset of field: _IO_FILE::_old_offset"]
|
||||
[::core::mem::offset_of!(_IO_FILE, _old_offset) - 120usize];
|
||||
["Offset of field: _IO_FILE::_cur_column"]
|
||||
|
|
@ -262,65 +117,16 @@ const _: () = {
|
|||
[::core::mem::offset_of!(_IO_FILE, _freeres_list) - 168usize];
|
||||
["Offset of field: _IO_FILE::_freeres_buf"]
|
||||
[::core::mem::offset_of!(_IO_FILE, _freeres_buf) - 176usize];
|
||||
["Offset of field: _IO_FILE::_prevchain"]
|
||||
[::core::mem::offset_of!(_IO_FILE, _prevchain) - 184usize];
|
||||
["Offset of field: _IO_FILE::__pad5"][::core::mem::offset_of!(_IO_FILE, __pad5) - 184usize];
|
||||
["Offset of field: _IO_FILE::_mode"][::core::mem::offset_of!(_IO_FILE, _mode) - 192usize];
|
||||
["Offset of field: _IO_FILE::_unused3"][::core::mem::offset_of!(_IO_FILE, _unused3) - 196usize];
|
||||
["Offset of field: _IO_FILE::_total_written"]
|
||||
[::core::mem::offset_of!(_IO_FILE, _total_written) - 200usize];
|
||||
["Offset of field: _IO_FILE::_unused2"][::core::mem::offset_of!(_IO_FILE, _unused2) - 208usize];
|
||||
["Offset of field: _IO_FILE::_unused2"][::core::mem::offset_of!(_IO_FILE, _unused2) - 196usize];
|
||||
};
|
||||
impl _IO_FILE {
|
||||
#[inline]
|
||||
pub fn _flags2(&self) -> libc::c_int {
|
||||
unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) }
|
||||
}
|
||||
#[inline]
|
||||
pub fn set__flags2(&mut self, val: libc::c_int) {
|
||||
unsafe {
|
||||
let val: u32 = ::core::mem::transmute(val);
|
||||
self._bitfield_1.set(0usize, 24u8, val as u64)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn _flags2_raw(this: *const Self) -> libc::c_int {
|
||||
unsafe {
|
||||
::core::mem::transmute(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get(
|
||||
::core::ptr::addr_of!((*this)._bitfield_1),
|
||||
0usize,
|
||||
24u8,
|
||||
) as u32)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub unsafe fn set__flags2_raw(this: *mut Self, val: libc::c_int) {
|
||||
unsafe {
|
||||
let val: u32 = ::core::mem::transmute(val);
|
||||
<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set(
|
||||
::core::ptr::addr_of_mut!((*this)._bitfield_1),
|
||||
0usize,
|
||||
24u8,
|
||||
val as u64,
|
||||
)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn new_bitfield_1(_flags2: libc::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> {
|
||||
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default();
|
||||
__bindgen_bitfield_unit.set(0usize, 24u8, {
|
||||
let _flags2: u32 = unsafe { ::core::mem::transmute(_flags2) };
|
||||
_flags2 as u64
|
||||
});
|
||||
__bindgen_bitfield_unit
|
||||
}
|
||||
}
|
||||
pub type va_list = __gnuc_va_list;
|
||||
unsafe extern "C" {
|
||||
pub fn vsnprintf(
|
||||
__s: *mut libc::c_char,
|
||||
__maxlen: libc::c_ulong,
|
||||
__format: *const libc::c_char,
|
||||
__arg: *mut __va_list_tag,
|
||||
__arg: VaList,
|
||||
) -> libc::c_int;
|
||||
}
|
||||
#[repr(C)]
|
||||
|
|
@ -338,7 +144,7 @@ unsafe extern "C" {
|
|||
unsafe extern "C" {
|
||||
pub fn libvlc_vprinterr(
|
||||
fmt: *const libc::c_char,
|
||||
ap: *mut __va_list_tag,
|
||||
ap: VaList,
|
||||
) -> *const libc::c_char;
|
||||
}
|
||||
unsafe extern "C" {
|
||||
|
|
@ -457,7 +263,7 @@ pub type libvlc_log_cb = ::core::option::Option<
|
|||
level: libc::c_int,
|
||||
ctx: *const libvlc_log_t,
|
||||
fmt: *const libc::c_char,
|
||||
args: *mut __va_list_tag,
|
||||
args: VaList,
|
||||
),
|
||||
>;
|
||||
unsafe extern "C" {
|
||||
|
|
@ -3404,25 +3210,3 @@ unsafe extern "C" {
|
|||
ppsz_options: *mut *mut libc::c_char,
|
||||
);
|
||||
}
|
||||
pub type __builtin_va_list = [__va_list_tag; 1usize];
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct __va_list_tag {
|
||||
pub gp_offset: libc::c_uint,
|
||||
pub fp_offset: libc::c_uint,
|
||||
pub overflow_arg_area: *mut libc::c_void,
|
||||
pub reg_save_area: *mut libc::c_void,
|
||||
}
|
||||
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
|
||||
const _: () = {
|
||||
["Size of __va_list_tag"][::core::mem::size_of::<__va_list_tag>() - 24usize];
|
||||
["Alignment of __va_list_tag"][::core::mem::align_of::<__va_list_tag>() - 8usize];
|
||||
["Offset of field: __va_list_tag::gp_offset"]
|
||||
[::core::mem::offset_of!(__va_list_tag, gp_offset) - 0usize];
|
||||
["Offset of field: __va_list_tag::fp_offset"]
|
||||
[::core::mem::offset_of!(__va_list_tag, fp_offset) - 4usize];
|
||||
["Offset of field: __va_list_tag::overflow_arg_area"]
|
||||
[::core::mem::offset_of!(__va_list_tag, overflow_arg_area) - 8usize];
|
||||
["Offset of field: __va_list_tag::reg_save_area"]
|
||||
[::core::mem::offset_of!(__va_list_tag, reg_save_area) - 16usize];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![no_std]
|
||||
|
||||
pub mod valist;
|
||||
|
||||
// The bindings are a committed source file, regenerated out of band with
|
||||
// `cargo xtask bindgen`.
|
||||
include!("../bindings.rs");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
//! Platform `va_list`, extracted and simplified from `core::ffi::va_list`.
|
||||
//!
|
||||
//! libvlc-sys rust bindings are common to all libvlc's supported platforms and are bindgen
|
||||
//! generated once by the maintainers. Hence it needs a cross-platform va_list type.
|
||||
//!
|
||||
//! VaLists are platform specific, the C standard only specifies that they should be possible to
|
||||
//! pass by value. Libvlc uses them in the logger callback exclusively, until the rust stdlib C
|
||||
//! variadic API is stable, the type with the single goal of being forwarded to a C formatting
|
||||
//! function. Which simplifies greatly the implementation.
|
||||
//!
|
||||
//! Once the c_variadic API is stabilized, this file should be removed.
|
||||
|
||||
/// [AArch64 Procedure Call Standard]:
|
||||
/// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#id110
|
||||
#[cfg(all(target_arch = "aarch64", not(target_vendor = "apple")))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VaList {
|
||||
stack: *mut libc::c_void,
|
||||
gr_top: *mut libc::c_void,
|
||||
vr_top: *mut libc::c_void,
|
||||
gr_offs: i32,
|
||||
vr_offs: i32,
|
||||
}
|
||||
|
||||
/// Everywhere else: either an opaque pointer already, or a pointer to the struct the array decayed
|
||||
/// into. This is sound since VaLists are only passed around.
|
||||
#[cfg(not(all(target_arch = "aarch64", not(target_vendor = "apple"))))]
|
||||
pub type VaList = *mut libc::c_void;
|
||||
|
|
@ -156,7 +156,7 @@ impl Drop for Instance {
|
|||
|
||||
const BUF_SIZE: usize = 1024; // Write log message to the buffer by vsnprintf.
|
||||
unsafe extern "C" fn logging_cb(
|
||||
data: *mut c_void, level: c_int, ctx: *const sys::libvlc_log_t, fmt: *const c_char, args: *mut sys::__va_list_tag) {
|
||||
data: *mut c_void, level: c_int, ctx: *const sys::libvlc_log_t, fmt: *const c_char, args: sys::VaList) {
|
||||
|
||||
let f: &Box<dyn Fn(LogLevel, Log, Cow<str>) + Send + 'static> = ::std::mem::transmute(data);
|
||||
let mut buf: [c_char; BUF_SIZE] = [0; BUF_SIZE];
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ fn generate_bindings() {
|
|||
.allowlist_item("(lib|LIB)?(vlc|VLC)_.*")
|
||||
// Required by the Windows `legacy_stdio_definitions` link workaround
|
||||
// (see libvlc-sys/build.rs).
|
||||
.allowlist_function("vsnprintf");
|
||||
.allowlist_function("vsnprintf")
|
||||
// Block the whole va_list family and rewrite the parameters bindings to our own `VaList`,
|
||||
// which is ABI-correct on every target.
|
||||
.blocklist_type(".*va_list.*")
|
||||
.raw_line("pub use crate::valist::VaList;");
|
||||
|
||||
for path in &library.include_paths {
|
||||
bindings = bindings.clang_arg(format!("-I{}", path.display()));
|
||||
|
|
@ -56,6 +60,14 @@ fn generate_bindings() {
|
|||
.expect("unable to generate bindings")
|
||||
.to_string();
|
||||
|
||||
let generated = generated
|
||||
.replace("*mut __va_list_tag", "VaList")
|
||||
.replace(": va_list", ": VaList");
|
||||
assert!(
|
||||
!generated.contains("va_list"),
|
||||
"a va_list spelling we do not know about survived"
|
||||
);
|
||||
|
||||
std::fs::write(&output, generated).expect("couldn't write bindings");
|
||||
println!("wrote {}", output.display());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue