I am trying to write a wrapper on top of winapi. I want to wrap functions that accept pointers for callback functions.
As an example, consider this:
// The unsafe callback type the FFI function accepts
type UnsafeCallback = unsafe extern "system" fn(exception_info: *mut ExceptionInfo) -> u32;
// The safe callback type my function should accept
type SafeCallback = fn(exception_info: &ConvertedExceptionInfo) -> u32;
The functions that will be used:
// The function exposed by winapi
unsafe extern "system" fn SetExceptionHandler(handler: UnsafeCallback);
// The function I want to expose in my library
fn SetExceptionHandler(handler: SafeCallback);
I want to create a wrapping function that looks like this:
unsafe extern "system" fn(exception_info: *mut ExceptionInfo) -> u32 {
let result = panic::catch_unwind(|| {
// Convert ExceptionInfo into ConvertedExceptionInfo. I know this is undefined behavior, but its only here
// to demonstrate program flow
let converted_exception_info: ConvertedExceptionInfo = (*exception_info).into();
// Call the corresponding safe function (as to how we get the function pointer here, that's
// the whole question)
return safe_callback(&converted_exception_info);
});
return match result {
Ok(val) => val,
Err(_) => _
};
}
I can think of two possibilities to create this wrapping function:
Creating a wrapping function at runtime
Create a closure or similar construct inside the safe
SetExceptionHandlermethod.I have no idea how to get the closure across the FFI boundary.
Exposing a conversion macro and generating the function at compile time
Edit the
SetExceptionHandlerfunction to accept theUnsafeCallbacktype.Then I could create a macro that generates the wrapping function at compile time and expose this macro to the user.
I would have to expose unsafe extern parameters again, so it is not how I would prefer to do it.
I have no idea how to structure such a macro or if this is even possible.
Is my first idea possible and feasible? If so, how could this be done? If not, is writing a macro like the second idea possible and feasible? If so, how could this be done?
Based on
- How do I create a Rust callback function to pass to a FFI function?
- How do I convert a Rust closure to a C-style callback?
- How do I pass a closure through raw pointers as an argument to a C function?
I get the impression that my first idea is probably not possible with the exception of something called trampolining.
Is trampolining possible in safe Rust and in this situation?
After much searching, i have found a blog post that explains a nice solution for the problem of wrapping callbacks. Article here