Skip to content

Commit

Permalink
Merge pull request #239 from getditto/dhm/niche-for-box-dyn-fn-and-fns
Browse files Browse the repository at this point in the history
Make `repr_c::Box<dyn FnMut…>` and by extension `fn` pointers, `Option`able
  • Loading branch information
danielhenrymantilla authored Sep 17, 2024
2 parents aaa4014 + 56e5088 commit 501b1d4
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 88 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ path = "src/_lib.rs"

[package]
name = "safer-ffi"
version = "0.1.12" # Keep in sync
version = "0.1.13" # Keep in sync
authors = ["Daniel Henry-Mantilla <[email protected]>"]
edition = "2021"
rust-version = "1.72.1"
Expand Down Expand Up @@ -90,6 +90,8 @@ serde_test = { version = "1.0.177" }
async-compat.optional = true
async-compat.version = "0.2.1"

extern-c.version = "0.1.0"

futures.optional = true
futures.version = "0.3.24"

Expand Down Expand Up @@ -141,7 +143,7 @@ version = "0.0.3"

[dependencies.safer_ffi-proc_macros]
path = "src/proc_macro"
version = "=0.1.12" # Keep in sync
version = "=0.1.13" # Keep in sync

[workspace]
members = [
Expand Down
11 changes: 9 additions & 2 deletions ffi_tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions js_tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 31 additions & 30 deletions src/closure/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,39 @@ macro_rules! with_tuple {(
}
{
env_ptr: ptr::NonNull<c_void>,
call:
call: Option<
unsafe extern "C"
fn (
env_ptr: ptr::NonNull<c_void> $(,
$A_N $(,
$A_k
)*)?
) -> Ret
,
free:
>,
free: Option<
unsafe extern "C"
fn (env_ptr: ptr::NonNull<c_void>)
,
>,
}
}

unsafe
impl<Ret $(, $A_N $(, $A_k)*)?>
$crate::layout::__HasNiche__
for
$BoxDynFnMut_N <Ret $(, $A_N $(, $A_k)*)?>
where
Ret : ReprC, $(
$A_N : ReprC, $(
$A_k : ReprC, )*)?
{}

/// `Box<dyn Send + ...> : Send`
unsafe
impl<Ret $(, $A_N $(, $A_k)*)?> Send
for $BoxDynFnMut_N <Ret $(, $A_N $(, $A_k)*)?>
impl<Ret $(, $A_N $(, $A_k)*)?>
Send
for
$BoxDynFnMut_N <Ret $(, $A_N $(, $A_k)*)?>
where
Ret : ReprC, $(
$A_N : ReprC, $(
Expand Down Expand Up @@ -93,7 +106,7 @@ macro_rules! with_tuple {(
{
#[inline]
pub
fn new<F> (f: rust::Box<F>) -> Self
fn new<F> (f: Box<F>) -> Self
where
F : FnMut( $($A_N $(, $A_k)*)? ) -> Ret,
F : Send + 'static,
Expand All @@ -102,33 +115,21 @@ macro_rules! with_tuple {(
// thanks to the generic bounds on F.
Self {
env_ptr: ptr::NonNull::from(Box::leak(f)).cast(),
free: {
unsafe extern "C"
fn free<F> (env_ptr: ptr::NonNull<c_void>)
where
F : Send + 'static,
{
drop::<Box<F>>(Box::from_raw(env_ptr.cast().as_ptr()));
}
free::<F>
},
call: {
unsafe extern "C"
fn call<F, Ret $(, $A_N $(, $A_k)*)?> (
free: Some(::extern_c::extern_c(|env_ptr: ptr::NonNull<c_void>| unsafe {
drop(Box::<F>::from_raw(env_ptr.cast().as_ptr()));
})),
call: Some(::extern_c::extern_c(
|
env_ptr: ptr::NonNull<c_void> $(,
$A_N : $A_N $(,
$A_k : $A_k )*)?
) -> Ret
where
F : FnMut($($A_N $(, $A_k)*)?) -> Ret,
F : Send + 'static,
| -> Ret
{
let mut env_ptr = env_ptr.cast();
let f: &mut F = env_ptr.as_mut();
let mut env_ptr: ptr::NonNull<F> = env_ptr.cast();
let f: &mut F = unsafe { env_ptr.as_mut() };
f( $($A_N $(, $A_k)*)? )
}
call::<F, Ret $(, $A_N $(, $A_k)*)?>
},
)),
}
}
}
Expand All @@ -143,7 +144,7 @@ macro_rules! with_tuple {(
fn drop (self: &'_ mut Self)
{
unsafe {
(self.free)(self.env_ptr)
self.free.expect("non-NULL `.free`")(self.env_ptr)
}
}
}
Expand All @@ -164,7 +165,7 @@ macro_rules! with_tuple {(
) -> Ret
{
unsafe {
(self.call)(self.env_ptr, $($A_N $(, $A_k)*)?)
self.call.expect("non-NULL `.call`")(self.env_ptr, $($A_N $(, $A_k)*)?)
}
}
}
Expand Down
70 changes: 21 additions & 49 deletions src/layout/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const _: () = { macro_rules! impl_CTypes {
}
#[cfg(docs)] impl_CTypes! { @fns (A1, A2) } #[cfg(not(docs))]
impl_CTypes! { @fns
(A9, A8, A7, A6, A5, A4, A3, A2, A1)
(A10, A9, A8, A7, A6, A5, A4, A3, A2, A1)
}
#[cfg(docs)] impl_CTypes! { @arrays 1 2 } #[cfg(not(docs))]
impl_CTypes! { @arrays
Expand Down Expand Up @@ -242,6 +242,26 @@ const _: () = { macro_rules! impl_CTypes {
}
)?

unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> $crate::layout::__HasNiche__
for
unsafe extern "C" fn ($($An, $($Ai ,)*)?) -> Ret
{}

unsafe
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> $crate::layout::__HasNiche__
for
/*unsafe*/ extern "C" fn ($($An, $($Ai ,)*)?) -> Ret
{}

// LegacyCType
/// Simplified for lighter documentation, but the actual impls include
/// **up to 9 function parameters**.
Expand Down Expand Up @@ -360,54 +380,6 @@ const _: () = { macro_rules! impl_CTypes {
}
} type OPAQUE_KIND = OpaqueKind::Concrete; }

/// Simplified for lighter documentation, but the actual impls include
/// **up to 9 function parameters**.
unsafe // Safety: byte-wise the layout is the same, but the safety
// invariants will still have to be checked at each site.
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for Option<unsafe extern "C" fn ($($An, $($Ai ,)*)?) -> Ret>
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;

#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}

/// Simplified for lighter documentation, but the actual impls include
/// **up to 9 function parameters**.
unsafe // Safety: byte-wise the layout is the same, but the safety
// invariants will still have to be checked at each site.
impl<
Ret : ReprC, $(
$An : ReprC, $(
$Ai : ReprC,
)*)?> ReprC
for Option</*unsafe*/ extern "C" fn ($($An, $($Ai ,)*)?) -> Ret>
{
type CLayout = Option<
unsafe extern "C"
fn ($($An::CLayout, $($Ai::CLayout ,)*)?) -> Ret::CLayout
>;

#[inline]
fn is_valid (_: &'_ Self::CLayout)
-> bool
{
true
}
}

/* == ReprC for Option-less == */

/// Simplified for lighter documentation, but the actual impls include
Expand Down
2 changes: 1 addition & 1 deletion src/proc_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ proc-macro = true

[package]
name = "safer_ffi-proc_macros"
version = "0.1.12" # Keep in sync
version = "0.1.13" # Keep in sync
authors = ["Daniel Henry-Mantilla <[email protected]>"]
edition = "2021"

Expand Down

0 comments on commit 501b1d4

Please sign in to comment.