split_closure with reverse order
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?
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 [email protected] 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 aTrailingDataTrampolineassociated type to theSplittrait. 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...