我正在尝试在 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
类型。然后我可以创建一个在编译时生成包装函数的宏,并将这个宏公开给用户。
我将不得不再次公开不安全的外部参数,所以这不是我希望这样做的方式。
我不知道如何构建这样的宏,或者这是否可能。
我的第一个想法可能可行吗?如果是这样,如何做到这一点?如果不是,那么编写像第二个想法这样的宏是否可行且可行?如果是这样,如何做到这一点?
基于
我的印象是,除了蹦床之外,我的第一个想法可能是不可能的。
在安全的 Rust 和这种情况下,蹦床是可能的吗?