windows - 如何安全包装回调传递给Windows FFI?

标签 windows winapi rust ffi trampolines

我试图在winapi上写一个包装器。我想包装接受回调函数指针的函数。
例如,考虑以下情况:

// 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 function exposed by winapi
unsafe extern "system" fn SetExceptionHandler(handler: UnsafeCallback);

// The function I want to expose in my library
fn SetExceptionHandler(handler: SafeCallback);
我想创建一个包装函数,如下所示:
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(_) => _
    };
}
我可以想到两种创建包装函数的可能性:
  • 在运行时创建包装函数
    在保险箱内创建一个闭合或类似的构造SetExceptionHandler方法。
    我不知道如何跨越FFI边界。
  • 公开转换宏并在编译时生成函数
    编辑SetExceptionHandler函数以接受UnsafeCallback类型。
    然后,我可以创建一个在编译时生成包装函数的宏,并将此宏向用户公开。
    我将不得不再次公开不安全的extern参数,所以它不是
    我更喜欢这样做。
    我不知道如何构造这样的宏,或者甚至是不可能的。

  • 我的第一个想法可能可行吗?如果是这样,怎么办呢?
    如果没有,那么编写像第二个想法这样的宏是否可能并且可行?如果是这样,怎么办呢?
    基于
  • 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?

  • 我的印象是,除了trampolining之类的东西外,我的第一个主意可能是不可能的。
    在这种情况下,可以在安全的Rust中进行蹦床吗?

    最佳答案

    经过大量搜索之后,我发现了一篇博客文章,该文章为包装回调问题提供了一个很好的解决方案。 Article here

    关于windows - 如何安全包装回调传递给Windows FFI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62565082/

    相关文章:

    python - 鼠标单击命令在某些 GUI 上不起作用

    c# - 如何使用网络 API 获取用户组

    rust - 使用包含借用参数的结构

    windows - `cargo build` 失败并出现链接错误 "link.exe failed: exit code: 325595"

    windows - 如何在单个文件中用 lf 替换 crlf

    c++ - RECT 和 POINT 数组之间的 reinterpret_cast 安全吗?

    c++ - 在主程序和 QProcess 之间同步输出?

    windows - Google Chrome 在 Windows 10(英语)中使用什么默认字体?

    windows - 批量高级防火墙异常(exception)(任何方向)

    rust - 如何在特定字符处拆分 &Path 的最后一个组件?