我有一个c函数,它将回调函数作为一个参数,我将把一个Obj-C包装器写入标准的C API。我想用块替换C回调。
让我们设想一个C API:
void audioStopFunction(void (*callback)(void *), void *udata);
Obj-C包装器如下所示:
- (void)myAudioStopFunction:(dispatch_block_t)block
{
void *udata = (__bridge void *)block;
audioStopFunction(my_callback, udata);
}
void my_callback(void *udata)
{
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}
现在,我有一些问题:
在myAudioStopFunction
函数中,我是否需要复制以下块:
void * udata =(__ bridge void *)[block copy];
在my_callback
函数中,我应该使用__bridge
代替__bridge_transfer
吗?此外,我是否需要在Block_release
之后致电block()
答案 0 :(得分:1)
由于C回调由包装器类管理,因此最容易让类管理块的所有权。 (我正在调用块completionBlock
,因为这似乎更符合Cocoa命名约定。)
@interface AudioCallbackWrapper
@property (nonatomic) dispatch_block_t completionBlock;
@end
static void my_callback(void *udata)
{
dispatch_block_t block = (__bridge dispatch_block_t)udata;
if (block != nil)
block();
}
@implementation AudioCallbackWrapper
- (void)setCompletionBlock:(dispatch_block_t)completionBlock
{
_completionBlock = [completionBlock copy];
audioStopFunction(my_callback, (__bridge void *)_completionBlock);
}
- (void)dealloc
{
// remove the C callback before completionBlock is released
self.completionBlock = nil;
}
@end
由于块的生命周期由封闭的包装器管理,因此C代码永远不必转移所有权。因此,代码仅包含__bridge
的{{1}}强制转换。
代码是否会导致内存泄漏?如果是,那么正确的方法是什么?
每次回调触发时,您的原始代码都会释放该块。第一次回调后,块指针将悬空。