mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-27 03:13:37 +08:00
Use * const u8
instead of * const c_void
The way cxx bridge works, it doesn't recognize any types from another module as being shared cxx bridge types with generations native to both C++ and Rust, meaning every module that was going to use function pointers would have to define its own `c_void` type (because cxx bridge doesn't recognize any of libc::c_void, std::ffi::c_void, or autocxx::c_void). FFI on other platforms has long used the equivalent of `uint8_t *` as an alternative to `void *` for code where `void` was not available or was undesirable for some reason. We can join the club - this way we can always use `* {const|mut} u8` in our rust code and `uint8_t *` in our C++ code to pass around parameters or values over the C abi.
This commit is contained in:
parent
4f6fe0999e
commit
aaf2d1c19d
|
@ -3,7 +3,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use self::fd_monitor::{c_void, new_fd_event_signaller, FdEventSignaller, ItemWakeReason};
|
||||
use self::fd_monitor::{new_fd_event_signaller, FdEventSignaller, ItemWakeReason};
|
||||
use crate::fd_readable_set::FdReadableSet;
|
||||
use crate::fds::AutoCloseFd;
|
||||
use crate::ffi::void_ptr;
|
||||
|
@ -25,11 +25,6 @@ mod fd_monitor {
|
|||
Poke,
|
||||
}
|
||||
|
||||
// Defines and exports a type shared between C++ and rust
|
||||
struct c_void {
|
||||
_unused: u8,
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("fds.h");
|
||||
|
||||
|
@ -59,8 +54,8 @@ mod fd_monitor {
|
|||
fn new_fd_monitor_item_ffi(
|
||||
fd: i32,
|
||||
timeout_usecs: u64,
|
||||
callback: *const c_void,
|
||||
param: *const c_void,
|
||||
callback: *const u8,
|
||||
param: *const u8,
|
||||
) -> Box<FdMonitorItem>;
|
||||
}
|
||||
|
||||
|
@ -76,8 +71,8 @@ mod fd_monitor {
|
|||
&mut self,
|
||||
fd: i32,
|
||||
timeout_usecs: u64,
|
||||
callback: *const c_void,
|
||||
param: *const c_void,
|
||||
callback: *const u8,
|
||||
param: *const u8,
|
||||
) -> u64;
|
||||
|
||||
#[cxx_name = "poke_item"]
|
||||
|
@ -221,13 +216,13 @@ impl FdMonitorItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_callback_ffi(&mut self, callback: *const c_void, param: *const c_void) {
|
||||
fn set_callback_ffi(&mut self, callback: *const u8, param: *const u8) {
|
||||
// Safety: we are just marshalling our function pointers with identical definitions on both
|
||||
// sides of the ffi bridge as void pointers to keep cxx bridge happy. Whether we invoke the
|
||||
// raw function as a void pointer or as a typed fn that helps us keep track of what we're
|
||||
// doing is unsafe in all cases, so might as well make the best of it.
|
||||
let callback = unsafe { std::mem::transmute(callback) };
|
||||
self.callback = FdMonitorCallback::Ffi(callback, void_ptr(param as _));
|
||||
self.callback = FdMonitorCallback::Ffi(callback, param.into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,8 +235,8 @@ fn new_fd_monitor_ffi() -> Box<FdMonitor> {
|
|||
fn new_fd_monitor_item_ffi(
|
||||
fd: RawFd,
|
||||
timeout_usecs: u64,
|
||||
callback: *const c_void,
|
||||
param: *const c_void,
|
||||
callback: *const u8,
|
||||
param: *const u8,
|
||||
) -> Box<FdMonitorItem> {
|
||||
// Safety: we are just marshalling our function pointers with identical definitions on both
|
||||
// sides of the ffi bridge as void pointers to keep cxx bridge happy. Whether we invoke the
|
||||
|
@ -250,7 +245,7 @@ fn new_fd_monitor_item_ffi(
|
|||
let callback = unsafe { std::mem::transmute(callback) };
|
||||
let mut item = FdMonitorItem::new();
|
||||
item.fd.reset(fd);
|
||||
item.callback = FdMonitorCallback::Ffi(callback, void_ptr(param as _));
|
||||
item.callback = FdMonitorCallback::Ffi(callback, param.into());
|
||||
if timeout_usecs != FdReadableSet::kNoTimeout {
|
||||
item.timeout = Some(Duration::from_micros(timeout_usecs));
|
||||
}
|
||||
|
@ -354,8 +349,8 @@ impl FdMonitor {
|
|||
&mut self,
|
||||
fd: RawFd,
|
||||
timeout_usecs: u64,
|
||||
callback: *const c_void,
|
||||
param: *const c_void,
|
||||
callback: *const u8,
|
||||
param: *const u8,
|
||||
) -> u64 {
|
||||
// Safety: we are just marshalling our function pointers with identical definitions on both
|
||||
// sides of the ffi bridge as void pointers to keep cxx bridge happy. Whether we invoke the
|
||||
|
@ -364,7 +359,7 @@ impl FdMonitor {
|
|||
let callback = unsafe { std::mem::transmute(callback) };
|
||||
let mut item = FdMonitorItem::new();
|
||||
item.fd.reset(fd);
|
||||
item.callback = FdMonitorCallback::Ffi(callback, void_ptr(param as _));
|
||||
item.callback = FdMonitorCallback::Ffi(callback, param.into());
|
||||
if timeout_usecs != FdReadableSet::kNoTimeout {
|
||||
item.timeout = Some(Duration::from_micros(timeout_usecs));
|
||||
}
|
||||
|
|
|
@ -151,3 +151,21 @@ impl core::fmt::Debug for void_ptr {
|
|||
|
||||
unsafe impl Send for void_ptr {}
|
||||
unsafe impl Sync for void_ptr {}
|
||||
|
||||
impl core::convert::From<*const core::ffi::c_void> for void_ptr {
|
||||
fn from(value: *const core::ffi::c_void) -> Self {
|
||||
Self(value as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<*const u8> for void_ptr {
|
||||
fn from(value: *const u8) -> Self {
|
||||
Self(value as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<*const autocxx::c_void> for void_ptr {
|
||||
fn from(value: *const autocxx::c_void) -> Self {
|
||||
Self(value as *const _)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -835,7 +835,7 @@ static void test_fd_monitor() {
|
|||
}
|
||||
}
|
||||
|
||||
static void trampoline(autoclose_fd_t2 &fd, item_wake_reason_t reason, c_void *param) {
|
||||
static void trampoline(autoclose_fd_t2 &fd, item_wake_reason_t reason, uint8_t *param) {
|
||||
auto &instance = *(item_maker_t*)(param);
|
||||
instance.callback(fd, reason);
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ static void test_fd_monitor() {
|
|||
explicit item_maker_t(uint64_t timeout_usec) {
|
||||
auto pipes = make_autoclose_pipes().acquire();
|
||||
writer = std::move(pipes.write);
|
||||
item = std::make_unique<rust::Box<fd_monitor_item_t>>(make_fd_monitor_item_t(pipes.read.acquire(), timeout_usec, (c_void *)item_maker_t::trampoline, (c_void*)this));
|
||||
item = std::make_unique<rust::Box<fd_monitor_item_t>>(make_fd_monitor_item_t(pipes.read.acquire(), timeout_usec, (uint8_t *)item_maker_t::trampoline, (uint8_t*)this));
|
||||
}
|
||||
|
||||
// Write 42 bytes to our write end.
|
||||
|
|
|
@ -121,7 +121,7 @@ void io_buffer_t::begin_filling(autoclose_fd_t fd) {
|
|||
args->promise = std::move(promise);
|
||||
|
||||
item_id_ =
|
||||
fd_monitor().add_item(fd.acquire(), kNoTimeout, (::c_void *)item_callback_trampoline, (::c_void *)args);
|
||||
fd_monitor().add_item(fd.acquire(), kNoTimeout, (uint8_t *)item_callback_trampoline, (uint8_t *)args);
|
||||
}
|
||||
|
||||
/// This is a hack to work around the difficulties in passing a capturing lambda across FFI
|
||||
|
|
Loading…
Reference in New Issue
Block a user