我正在使用CoreFoundationOS X上的框架,但我不知道如何在Rust中映射此函数:
void CFRunLoopPerformBlock(CFRunLoopRef fl, CFTypeRef mode, void (^block)(void));
Run Code Online (Sandbox Code Playgroud)
最后一个参数是void(^block)(void)- 如何创建此类型的参数?
简短,可能有用的答案:有block箱子,看起来它可能会起作用.
简短而无益的答案:就我所知,Rust对Apple的块扩展没有任何支持.假设您要调用期望块的API,则没有等效的Rust类型.
时间越长,稍微少无益的答案:从我可以从收集的苹果块ABI一些铛文档,void(^)(void)将大小作为一个普通指针一样.
因此,我的建议如下:将块视为不透明,指针大小的值.要调用一个,请在C中编写一个函数,为您调用它.
以下是未经测试的(我没有Mac),但至少应该让你朝着正确的方向前进.此外,我正在标记这个社区维基,所以任何可以测试它的人都可以在需要时修复它.
在Rust:
// These are the "raw" representations involved. I'm not using std::raw
// because that's not yet stabilised.
#[deriving(Copy, Clone)]
struct AppleBlock(*const ());
#[deriving(Copy, Clone)]
struct RustClosure(*const(), *const());
// Functions that we need to be written in C:
extern "C" {
fn rust_closure_to_block(closure_blob: RustClosure) -> AppleBlock;
fn block_release(block_blob: AppleBlock);
}
// The function that the C code will need. Note that this is *specific* to
// FnMut() closures. If you wanted to generalise this, you could write a
// generic version and pass a pointer to that to `rust_closure_to_block`.
extern "C" fn call_rust_closure(closure_blob: RustClosure) {
let closure_ref: &FnMut() = unsafe { mem::transmute(closure_blob) };
closure_ref();
}
// This is what you call in order to *temporarily* turn a closure into a
// block. So, you'd use it as:
//
// with_closure_as_block(
// || do_stuff(),
// |block| CFRunLoopPerformBlock(fl, mode, block)
// );
fn with_closure_as_block<C, B, R>(closure: C, body: B) -> R
where C: FnMut(), B: FnOnce(block_blob) -> R {
let closure_ref: &FnMut() = &closure;
let closure_blob: RustClosure = unsafe { mem::transmute(closure_ref) };
let block_blob = unsafe { rust_closure_to_block(closure_blob) };
let r = body(block_blob);
unsafe { block_release(block_blob) };
r
}
Run Code Online (Sandbox Code Playgroud)
在C:
typedef struct AppleBlock {
void *ptr;
} AppleBlock;
typedef struct RustClosure {
void *ptr;
void *vt;
} RustClosure;
void call_rust_closure(RustClosure closure_blob);
AppleBlock rust_closure_to_block(RustClosure closure_blob) {
return (AppleBlock)Block_copy(^() {
call_rust_closure(closure_blob);
});
}
// I'm not using Block_release directly because I don't know if or how
// blocks change name mangling or calling. You might be able to just
// use Block_release directly from Rust.
void block_release(AppleBlock block) {
Block_release((void (^)(void))block);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
170 次 |
| 最近记录: |