gpt4 book ai didi

objective-c - 按 block 包装 c 回调(__bridge_transfer 和 block )

转载 作者:搜寻专家 更新时间:2023-10-30 20:20:48 24 4
gpt4 key购买 nike

我正在为标准 C API 编写 Obj-C 包装器。我想用 block 替换 C 回调。

让我们想象一个 C API:

void my_async_function(void (* callback)(void *), void *udata);

Obj-C 包装器如下所示:

- (void)myAsyncFunction:(dispatch_block_t)block
{
void *udata = (__bridge_retained void *)block;
my_async_function(my_callback, udata);
}

void my_callback(void *udata)
{
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}

__bridge_retained__bridge_transfer 在许多情况下工作良好,但在 block 上,它们会导致非常奇怪的行为。

myAsyncFunction: 的汇编代码完全没有保留(Xcode 4.4、ARC、O3)。

非常奇怪的是,下面的核心生成了一个 objc_retainBlock,这是我对 myAsyncFunction 的预期:

void *a_global_var;

- (void)myAsyncFunction2:(dispatch_block_t)block
{
void *udata = (__bridge_retained void *)block;
a_global_var = udata;
my_async_function(my_callback, udata);
}

我们可以将其称为编译器的错误吗?如果不是,编译器遵循什么规则?

类似主题:

最佳答案

尝试:

- (void)myAsyncFunction:(dispatch_block_t)block
{
void *udata = (__bridge_transfer void *) [block copy];
my_async_function(my_callback, udata);
}

void my_callback(void *udata)
{
// however, see the comment in the last paragraph
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}

通常,编译器在 Block_copy 中进行综合当您将 block 指针分配给一个位置时调用 where it could outlive the block structure it references .

但是,编译器无法知道将 void* 传递给 C api 后会发生什么,并且无论如何您都在覆盖编译器可能认为它应该对 __bridge_retained 做的任何事情。称呼。在存储引用时保留 block 是不够的。

此外,即使进行了此更改,您的回调也必须恰好调用一次,因为它负责释放 block 。如果它永远不会被调用,你就会泄漏这个 block 。如果它被多次调用,你就会崩溃。因此,您可能希望让包装类的实例负责管理 block 的内存,除非 C api 允许您提供清理函数,您可以使用该函数来释放 block 。

关于objective-c - 按 block 包装 c 回调(__bridge_transfer 和 block ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11738248/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com