1

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:

  1. Creating a wrapping function at runtime

    Create a closure or similar construct inside the safe SetExceptionHandler method.

    I have no idea how to get the closure across the FFI boundary.

  2. Exposing a conversion macro and generating the function at compile time

    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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Erik Schulze
  • 119
  • 9
  • It looks like your question might be answered by the answers of [How do I create a Rust callback function to pass to a FFI function?](https://stackoverflow.com/q/31463426/155423); [How do I convert a Rust closure to a C-style callback?](https://stackoverflow.com/q/32270030/155423); [How do I pass a closure through raw pointers as an argument to a C function?](https://stackoverflow.com/q/38995701/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jun 25 '20 at 00:20
  • @Shepmaster I have edited my Question in Response. Thank you for your edit and links to simmilar Questions. – Erik Schulze Jun 25 '20 at 02:10

1 Answers1

0

After much searching, i have found a blog post that explains a nice solution for the problem of wrapping callbacks. Article here

Erik Schulze
  • 119
  • 9