Open andoriyu opened 4 years ago
One way this could be implemented is to add some sort of trailing_data_trampoline()
method and a TrailingDataTrampoline
associated type to the Split
trait. This would return a "trampoline" function that accepts the user data pointer as the last argument.
I'd be happy to mentor a PR if you are interested in implementing this.
Yeah, I'm interested. I made trampoline already for my use case, but that one is specific to my function.
On Wed, Apr 8, 2020, 1:04 AM Michael Bryan notifications@github.com wrote:
One way this could be implemented is to add some sort of trailing_data_trampoline() method and a TrailingDataTrampoline associated type to the Split trait https://github.com/Michael-F-Bryan/ffi_helpers/blob/master/src/split.rs. This would return a "trampoline" function that accepts the user data pointer as the last argument.
I'd be happy to mentor a PR if you are interested in implementing this.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Michael-F-Bryan/ffi_helpers/issues/1#issuecomment-610814288, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABEFGZIN3X44HBWLMNPKOLRLQVY7ANCNFSM4MDSXGZQ .
I've been trying to modify your macro for use with trailing c_void
but the compiler is still giving me errors. This is probably because I have no idea what I'm doing and have just been hacking around!
What is that I don't understand about dealing with code after the trailing repeated identifiers? I haven't been able to find any docs or examples to help...
This:
macro_rules! impl_split {
($( $outer:ident ),* ; $( $inner:ident ),*) => {
impl<Func, Ret, $($outer),*> Split<($( $outer, )*), Ret> for Func
where
Func: FnMut($($outer),*) -> Ret,
{
type Trampoline = unsafe extern "C" fn($($outer),*, *mut c_void) -> Ret;
fn trampoline() -> Self::Trampoline {
// declare a trampoline function which will turn our pointer
// back into an `F` and invoke it
// Note: we're deliberately using `$inner` to generate an ident
// for the argument
#[allow(non_snake_case)]
unsafe extern "C" fn trampoline<T, Ret_, $( $inner ),*>($($inner: $inner),* ptr: *mut c_void) -> Ret_
where
T: FnMut($($inner),*) -> Ret_,
{
debug_assert!(!ptr.is_null());
let callback: &mut T = &mut *(ptr as *mut T);
callback($($inner),*)
}
trampoline::<Func, Ret, $($outer,)*>
}
}
};
}
Gives me two errors. I've tried all sorts of combinations of coma etc and it doesn't seem to want comma anywhere 🤷♂️
error: expected argument name, found `,`
|
22 | type Trampoline = unsafe extern "C" fn($($outer),*, *mut c_void) -> Ret;
| ^ expected argument name
error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `ptr`
|
31 | unsafe extern "C" fn trampoline<T, Ret_, $( $inner ),*>($($inner: $inner),* ptr: *mut c_void) -> Ret_
| - ^^^ expected one of 7 possible tokens
| |
| help: missing `,`
...
As is generally always the case, I managed to get it working shortly after posting the above:
macro_rules! impl_split {
($( $outer:ident ),* ; $( $inner:ident ),*) => {
impl<Func, Ret, $($outer),*> Split<($( $outer, )*), Ret> for Func
where
Func: FnMut($($outer),*) -> Ret,
{
type Trampoline = unsafe extern "C" fn($($outer,)* *mut c_void) -> Ret;
fn trampoline() -> Self::Trampoline {
// declare a trampoline function which will turn our pointer
// back into an `F` and invoke it
// Note: we're deliberately using `$inner` to generate an ident
// for the argument
#[allow(non_snake_case)]
unsafe extern "C" fn trampoline<T, Ret_, $( $inner ),*>($($inner: $inner,)* ptr: *mut c_void) -> Ret_
where
T: FnMut($($inner),*) -> Ret_,
{
debug_assert!(!ptr.is_null());
let callback: &mut T = &mut *(ptr as *mut T);
callback($($inner),*)
}
trampoline::<Func, Ret, $($outer,)*>
}
}
};
}
Hi ! This feature would be great to have. Is it still on the agenda?
edit: Thx @timfish ! For the moment i just forked this rep and replaced the macro with your version. Works great. 😄 I wish I was more prolific in Rust yet so I could help with a trait and a PR, but macros are still a bit too much for me.
One way this could be implemented is to add some sort of
trailing_data_trampoline()
method and aTrailingDataTrampoline
associated type to theSplit
trait. This would return a "trampoline" function that accepts the user data pointer as the last argument.I'd be happy to mentor a PR if you are interested in implementing this.
Hey @Michael-F-Bryan
I went ahead and implemented the trait and another split function. Submitting a pull request and I am looking forward to your input. You seem to be very experienced in Rust and I am always happy to learn some more.
I've seen on your blog that you are also from Perth. What a coincidence 😁. Alrighty, that's it for now...
Hello, sweet library that I've discovered just in time. However, C function I'm working is passes user data as last argument.
Is it possible to add another function to support that use case?