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:
Create a closure or similar construct inside the safe
SetExceptionHandler
method.
I have no idea how to get the closure across the FFI boundary.
Edit the SetExceptionHandler
function to accept the UnsafeCallback
type.
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
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