Skip to content

Commit 09de658

Browse files
committed
Use fn-ptr instead of impl_fn macro
1 parent 8334385 commit 09de658

File tree

4 files changed

+48
-153
lines changed

4 files changed

+48
-153
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ derive_more = { version = "2.0", features = ["deref", "from", "display"], defaul
1818
hostfxr-sys = { version = "0.12", features = ["enum-map", "undocumented", "wrapper", "optional-apis"], default-features = false }
1919
coreclr-hosting-shared = { version = "0.1", default-features = false }
2020
destruct-drop = { version = "0.2", default-features = false }
21-
ffi-opaque = { version = "2.0", default-features = false }
2221
enum-map = { version = "2.7", default-features = false }
2322
once_cell = { version = "1.21", default-features = false }
23+
fn-ptr = { version = "0.4", default-features = false }
2424
nethost-sys = { version = "0.7", optional = true, default-features = false }
2525

2626
[target.'cfg(windows)'.dependencies]

src/hostfxr/context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
error::{HostingError, HostingResult, HostingSuccess},
66
hostfxr::{
77
AppOrHostingResult, AssemblyDelegateLoader, DelegateLoader, Hostfxr, HostfxrLibrary,
8-
RawFunctionPtr, SharedHostfxrLibrary,
8+
RawFnPtr, SharedHostfxrLibrary,
99
},
1010
pdcstring::PdCString,
1111
};
@@ -83,7 +83,7 @@ pub struct HostfxrContext<I> {
8383
handle: HostfxrHandle,
8484
hostfxr: SharedHostfxrLibrary,
8585
is_primary: bool,
86-
runtime_delegates: EnumMap<hostfxr_delegate_type, OnceCell<RawFunctionPtr>>,
86+
runtime_delegates: EnumMap<hostfxr_delegate_type, OnceCell<RawFnPtr>>,
8787
context_type: PhantomData<I>,
8888
not_sync: PhantomData<Cell<HostfxrLibrary>>,
8989
}
@@ -171,15 +171,15 @@ impl<I> HostfxrContext<I> {
171171
pub fn get_runtime_delegate(
172172
&self,
173173
r#type: hostfxr_delegate_type,
174-
) -> Result<RawFunctionPtr, HostingError> {
174+
) -> Result<RawFnPtr, HostingError> {
175175
self.runtime_delegates[r#type]
176176
.get_or_try_init(|| self.get_runtime_delegate_uncached(r#type))
177177
.copied()
178178
}
179179
fn get_runtime_delegate_uncached(
180180
&self,
181181
r#type: hostfxr_delegate_type,
182-
) -> Result<RawFunctionPtr, HostingError> {
182+
) -> Result<RawFnPtr, HostingError> {
183183
let mut delegate = MaybeUninit::uninit();
184184
let result = unsafe {
185185
self.hostfxr.hostfxr_get_runtime_delegate(

src/hostfxr/delegate_loader.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ use num_enum::TryFromPrimitive;
1010
use std::{convert::TryFrom, mem::MaybeUninit, path::Path, ptr};
1111
use thiserror::Error;
1212

13-
use super::{FunctionPtr, ManagedFunction, RawFunctionPtr, SharedHostfxrLibrary};
13+
use super::{as_managed, FnPtr, ManagedFunction, RawFnPtr, SharedHostfxrLibrary};
1414

1515
#[cfg(feature = "net5_0")]
1616
use crate::bindings::hostfxr::{get_function_pointer_fn, UNMANAGED_CALLERS_ONLY_METHOD};
1717

1818
/// A pointer to a function with the default signature.
1919
pub type ManagedFunctionWithDefaultSignature = ManagedFunction<component_entry_point_fn>;
2020
/// A pointer to a function with an unknown signature.
21-
pub type ManagedFunctionWithUnknownSignature = ManagedFunction<RawFunctionPtr>;
21+
pub type ManagedFunctionWithUnknownSignature = ManagedFunction<RawFnPtr>;
2222

2323
/// A struct for loading pointers to managed functions for a given [`HostfxrContext`].
2424
///
@@ -52,7 +52,7 @@ impl DelegateLoader {
5252
type_name: *const char_t,
5353
method_name: *const char_t,
5454
delegate_type_name: *const char_t,
55-
) -> Result<RawFunctionPtr, GetManagedFunctionError> {
55+
) -> Result<RawFnPtr, GetManagedFunctionError> {
5656
let mut delegate = MaybeUninit::uninit();
5757

5858
let result = unsafe {
@@ -94,7 +94,7 @@ impl DelegateLoader {
9494
type_name: *const char_t,
9595
method_name: *const char_t,
9696
delegate_type_name: *const char_t,
97-
) -> Result<RawFunctionPtr, GetManagedFunctionError> {
97+
) -> Result<RawFnPtr, GetManagedFunctionError> {
9898
let mut delegate = MaybeUninit::uninit();
9999

100100
let result = unsafe {
@@ -128,13 +128,13 @@ impl DelegateLoader {
128128
/// Name of the method on the `type_name` to find. The method must be static and must match the signature of `delegate_type_name`.
129129
/// * `delegate_type_name`:
130130
/// Assembly qualified delegate type name for the method signature.
131-
pub fn load_assembly_and_get_function<F: FunctionPtr>(
131+
pub fn load_assembly_and_get_function<F: FnPtr>(
132132
&self,
133133
assembly_path: &PdCStr,
134134
type_name: &PdCStr,
135135
method_name: &PdCStr,
136136
delegate_type_name: &PdCStr,
137-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
137+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
138138
Self::validate_assembly_path(assembly_path)?;
139139
let function = unsafe {
140140
self.load_assembly_and_get_function_pointer_raw(
@@ -144,7 +144,9 @@ impl DelegateLoader {
144144
delegate_type_name.as_ptr(),
145145
)
146146
}?;
147-
Ok(ManagedFunction(unsafe { F::Managed::from_ptr(function) }))
147+
Ok(ManagedFunction(unsafe {
148+
<as_managed!(F)>::from_ptr(function)
149+
}))
148150
}
149151

150152
/// Calling this function will load the specified assembly in isolation (into its own `AssemblyLoadContext`)
@@ -177,7 +179,7 @@ impl DelegateLoader {
177179
ptr::null(),
178180
)
179181
}?;
180-
Ok(ManagedFunction(unsafe { FunctionPtr::from_ptr(function) }))
182+
Ok(ManagedFunction(unsafe { FnPtr::from_ptr(function) }))
181183
}
182184

183185
/// Calling this function will load the specified assembly in isolation (into its own `AssemblyLoadContext`)
@@ -199,12 +201,12 @@ impl DelegateLoader {
199201
/// [UnmanagedCallersOnly]: <https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute>
200202
#[cfg(feature = "net5_0")]
201203
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "net5_0")))]
202-
pub fn load_assembly_and_get_function_with_unmanaged_callers_only<F: FunctionPtr>(
204+
pub fn load_assembly_and_get_function_with_unmanaged_callers_only<F: FnPtr>(
203205
&self,
204206
assembly_path: &PdCStr,
205207
type_name: &PdCStr,
206208
method_name: &PdCStr,
207-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
209+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
208210
Self::validate_assembly_path(assembly_path)?;
209211
let function = unsafe {
210212
self.load_assembly_and_get_function_pointer_raw(
@@ -214,7 +216,9 @@ impl DelegateLoader {
214216
UNMANAGED_CALLERS_ONLY_METHOD,
215217
)
216218
}?;
217-
Ok(ManagedFunction(unsafe { F::Managed::from_ptr(function) }))
219+
Ok(ManagedFunction(unsafe {
220+
<as_managed!(F)>::from_ptr(function)
221+
}))
218222
}
219223

220224
/// Calling this function will find the specified type and method and return a native function pointer to that method.
@@ -229,20 +233,22 @@ impl DelegateLoader {
229233
/// Assembly qualified delegate type name for the method signature.
230234
#[cfg(feature = "net5_0")]
231235
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "net5_0")))]
232-
pub fn get_function<F: FunctionPtr>(
236+
pub fn get_function<F: FnPtr>(
233237
&self,
234238
type_name: &PdCStr,
235239
method_name: &PdCStr,
236240
delegate_type_name: &PdCStr,
237-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
241+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
238242
let function = unsafe {
239243
self.get_function_pointer_raw(
240244
type_name.as_ptr(),
241245
method_name.as_ptr(),
242246
delegate_type_name.as_ptr(),
243247
)
244248
}?;
245-
Ok(ManagedFunction(unsafe { F::Managed::from_ptr(function) }))
249+
Ok(ManagedFunction(unsafe {
250+
<as_managed!(F)>::from_ptr(function)
251+
}))
246252
}
247253

248254
/// Calling this function will find the specified type and method and return a native function pointer to that method.
@@ -263,7 +269,7 @@ impl DelegateLoader {
263269
let function = unsafe {
264270
self.get_function_pointer_raw(type_name.as_ptr(), method_name.as_ptr(), ptr::null())
265271
}?;
266-
Ok(ManagedFunction(unsafe { FunctionPtr::from_ptr(function) }))
272+
Ok(ManagedFunction(unsafe { FnPtr::from_ptr(function) }))
267273
}
268274

269275
/// Calling this function will find the specified type and method and return a native function pointer to that method.
@@ -279,19 +285,21 @@ impl DelegateLoader {
279285
/// [`UnmanagedCallersOnly`]: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute
280286
#[cfg(feature = "net5_0")]
281287
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "net5_0")))]
282-
pub fn get_function_with_unmanaged_callers_only<F: FunctionPtr>(
288+
pub fn get_function_with_unmanaged_callers_only<F: FnPtr>(
283289
&self,
284290
type_name: &PdCStr,
285291
method_name: &PdCStr,
286-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
292+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
287293
let function = unsafe {
288294
self.get_function_pointer_raw(
289295
type_name.as_ptr(),
290296
method_name.as_ptr(),
291297
UNMANAGED_CALLERS_ONLY_METHOD,
292298
)
293299
}?;
294-
Ok(ManagedFunction(unsafe { F::Managed::from_ptr(function) }))
300+
Ok(ManagedFunction(unsafe {
301+
<as_managed!(F)>::from_ptr(function)
302+
}))
295303
}
296304
}
297305

@@ -330,12 +338,12 @@ impl AssemblyDelegateLoader {
330338
/// Name of the method on the `type_name` to find. The method must be static and must match the signature of `delegate_type_name`.
331339
/// * `delegate_type_name`:
332340
/// Assembly qualified delegate type name for the method signature.
333-
pub fn get_function<F: FunctionPtr>(
341+
pub fn get_function<F: FnPtr>(
334342
&self,
335343
type_name: &PdCStr,
336344
method_name: &PdCStr,
337345
delegate_type_name: &PdCStr,
338-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
346+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
339347
self.loader.load_assembly_and_get_function::<F>(
340348
self.assembly_path.as_ref(),
341349
type_name,
@@ -385,11 +393,11 @@ impl AssemblyDelegateLoader {
385393
/// [`UnmanagedCallersOnly`]: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute
386394
#[cfg(feature = "net5_0")]
387395
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "net5_0")))]
388-
pub fn get_function_with_unmanaged_callers_only<F: FunctionPtr>(
396+
pub fn get_function_with_unmanaged_callers_only<F: FnPtr>(
389397
&self,
390398
type_name: &PdCStr,
391399
method_name: &PdCStr,
392-
) -> Result<ManagedFunction<F::Managed>, GetManagedFunctionError> {
400+
) -> Result<ManagedFunction<as_managed!(F)>, GetManagedFunctionError> {
393401
self.loader
394402
.load_assembly_and_get_function_with_unmanaged_callers_only::<F>(
395403
self.assembly_path.as_ref(),

src/hostfxr/managed_function.rs

Lines changed: 13 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::{fmt::Debug, ops::Deref};
22

3+
pub use fn_ptr::{FnPtr, UntypedFnPtr as RawFnPtr};
4+
35
/// A wrapper around a managed function pointer.
4-
pub struct ManagedFunction<F: ManagedFunctionPtr>(pub(crate) F);
6+
pub struct ManagedFunction<F: ManagedFnPtr>(pub(crate) F);
57

6-
impl<F: ManagedFunctionPtr> Debug for ManagedFunction<F> {
8+
impl<F: ManagedFnPtr> Debug for ManagedFunction<F> {
79
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
810
f.debug_struct("ManagedFunction")
911
.field("ptr", &self.0.as_ptr())
@@ -12,139 +14,24 @@ impl<F: ManagedFunctionPtr> Debug for ManagedFunction<F> {
1214
}
1315
}
1416

15-
impl<F: ManagedFunctionPtr> Deref for ManagedFunction<F> {
17+
impl<F: ManagedFnPtr> Deref for ManagedFunction<F> {
1618
type Target = F;
1719

1820
fn deref(&self) -> &Self::Target {
1921
&self.0
2022
}
2123
}
2224

23-
ffi_opaque::opaque! {
24-
/// A struct representing an opaque function.
25-
pub struct OpaqueFunction;
26-
}
27-
28-
/// Type alias for a raw untyped function pointer.
29-
pub type RawFunctionPtr = *const OpaqueFunction;
30-
31-
/// Trait representing a function pointer.
32-
///
33-
/// # Safety
34-
/// This trait should only be implemented for function pointers and the associated types and constants have to match the function pointer type.
35-
pub unsafe trait FunctionPtr: Sized + Copy + Send + Sync + 'static {
36-
/// The argument types as a tuple.
37-
type Args;
38-
39-
/// The return type.
40-
type Output;
41-
42-
/// The function's arity (number of arguments).
43-
const ARITY: usize;
44-
45-
/// The `extern "system"` version of this function pointer.
46-
type Managed: ManagedFunctionPtr;
47-
48-
/// Constructs a [`FunctionPtr`] from an untyped function pointer.
49-
///
50-
/// # Safety
51-
/// This function is unsafe because it can not check if the argument points to a function
52-
/// of the correct type.
53-
unsafe fn from_ptr(ptr: RawFunctionPtr) -> Self;
54-
55-
/// Returns a untyped function pointer for this function.
56-
fn as_ptr(&self) -> RawFunctionPtr;
57-
}
58-
5925
/// Trait representing a managed function pointer.
60-
///
61-
/// # Safety
62-
/// This trait should only be implemented for `extern "system"` function pointers and the associated types and constants have to match the function pointer type.
63-
pub unsafe trait ManagedFunctionPtr: FunctionPtr {
64-
/// The argument types as a tuple.
65-
type Args;
66-
67-
/// The return type.
68-
type Output;
69-
70-
/// The function's arity (number of arguments).
71-
const ARITY: usize;
72-
}
73-
74-
macro_rules! impl_fn {
75-
(@recurse () ($($nm:ident : $ty:ident),*)) => {
76-
impl_fn!(@impl_all ($($nm : $ty),*));
77-
};
78-
(@recurse ($hd_nm:ident : $hd_ty:ident $(, $tl_nm:ident : $tl_ty:ident)*) ($($nm:ident : $ty:ident),*)) => {
79-
impl_fn!(@impl_all ($($nm : $ty),*));
80-
impl_fn!(@recurse ($($tl_nm : $tl_ty),*) ($($nm : $ty,)* $hd_nm : $hd_ty));
81-
};
82-
83-
(@impl_all ($($nm:ident : $ty:ident),*)) => {
84-
impl_fn!(@impl_u_and_s ($($nm : $ty),*) fn($($ty),*) -> Ret);
85-
};
86-
87-
(@impl_u_and_s ($($nm:ident : $ty:ident),*) fn($($param_ty:ident),*) -> $ret:ty) => {
88-
impl_fn!(@impl_core ($($nm : $ty),*) (fn($($param_ty),*) -> $ret) (extern "system" fn($($param_ty),*) -> $ret));
89-
impl_fn!(@impl_core ($($nm : $ty),*) (unsafe fn($($param_ty),*) -> $ret) (unsafe extern "system" fn($($param_ty),*) -> $ret));
90-
};
91-
92-
(@impl_core ($($nm:ident : $ty:ident),*) ($fn_type:ty) ($managed_fn_type:ty)) => {
93-
unsafe impl<Ret: 'static, $($ty: 'static),*> crate::hostfxr::FunctionPtr for $fn_type {
94-
type Args = ($($ty,)*);
95-
type Output = Ret;
96-
type Managed = $managed_fn_type;
97-
98-
const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
99-
100-
unsafe fn from_ptr(ptr: crate::hostfxr::RawFunctionPtr) -> Self {
101-
::core::assert!(!ptr.is_null());
102-
unsafe { ::core::mem::transmute(ptr) }
103-
}
104-
105-
fn as_ptr(&self) -> crate::hostfxr::RawFunctionPtr {
106-
*self as crate::hostfxr::RawFunctionPtr
107-
}
108-
}
109-
110-
unsafe impl<Ret: 'static, $($ty: 'static),*> crate::hostfxr::FunctionPtr for $managed_fn_type {
111-
type Args = ($($ty,)*);
112-
type Output = Ret;
113-
type Managed = $managed_fn_type;
114-
115-
const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
26+
pub trait ManagedFnPtr: fn_ptr::FnPtr + fn_ptr::HasAbi<{ fn_ptr::abi!("system") }> {}
11627

117-
unsafe fn from_ptr(ptr: crate::hostfxr::RawFunctionPtr) -> Self {
118-
::core::assert!(!ptr.is_null());
119-
unsafe { ::core::mem::transmute(ptr) }
120-
}
28+
impl<T: fn_ptr::FnPtr + fn_ptr::HasAbi<{ fn_ptr::abi!("system") }>> ManagedFnPtr for T {}
12129

122-
fn as_ptr(&self) -> crate::hostfxr::RawFunctionPtr {
123-
*self as crate::hostfxr::RawFunctionPtr
124-
}
125-
}
126-
127-
unsafe impl<Ret: 'static, $($ty: 'static),*> crate::hostfxr::ManagedFunctionPtr for $managed_fn_type {
128-
type Args = ($($ty,)*);
129-
type Output = Ret;
130-
131-
const ARITY: ::core::primitive::usize = impl_fn!(@count ($($ty)*));
132-
}
133-
};
134-
135-
(@count ()) => {
136-
0
137-
};
138-
(@count ($hd:tt $($tl:tt)*)) => {
139-
1 + impl_fn!(@count ($($tl)*))
30+
#[macro_export]
31+
#[doc(hidden)]
32+
macro_rules! __as_managed {
33+
($t:ty) => {
34+
::fn_ptr::with_abi!(::fn_ptr::Abi::System, $t)
14035
};
141-
142-
($($nm:ident : $ty:ident),*) => {
143-
impl_fn!(@recurse ($($nm : $ty),*) ());
144-
};
145-
}
146-
147-
impl_fn! {
148-
__arg_0: A, __arg_1: B, __arg_2: C, __arg_3: D, __arg_4: E, __arg_5: F, __arg_6: G,
149-
__arg_7: H, __arg_8: I, __arg_9: J, __arg_10: K, __arg_11: L
15036
}
37+
pub(crate) use __as_managed as as_managed;

0 commit comments

Comments
 (0)