'Casting'C回调到Objective-C块

时间:2017-02-14 11:30:58

标签: objective-c

我一直在阅读Objective-C块(例如在Apple documentationa blog postonetwothree Stack Overflow答案)。我想将C / C ++样式的回调传递给Objective-C方法。

这是我在C / C ++方面的声明

#ifdef __cplusplus
extern "C" {
#endif

    typedef void (*CALCULATION_CALLBACK)(int x);
    void setCubeCallback(int x, CALCULATION_CALLBACK callback);

#ifdef __cplusplus
}
#endif

并在Objective-C

@interface IOSPluginTest : NSObject

typedef void (^CalculationHandler)(int x);
-(void)cubeThisNumber:(int)number andCallbackOn:(CalculationHandler)callback;

@end

这是Objective-C实现

#import "IOSPluginTest.h"

@implementation IOSPluginTest

-(void)cubeThisNumber:(int)number andCallbackOn:(CalculationHandler)callback {
    int result = number * number * number;
    if (callback != nil) {
        callback(result);
    }
}

@end

最后一点,C / C ++实现出了问题

void setCubeCallback(int x, CALCULATION_CALLBACK callback) {
    [[[IOSPluginTest alloc] init] cubeThisNumber:x andCallbackOn:callback];
}

无法使用错误编译

  

将'CALCULATION_CALLBACK'(又名'void(*)(int)')发送到不兼容类型'CalculationHandler'的参数(又名'void(^)(int)')

这两种类型的描述void(*)(int)void(^)(int)看起来与我很相似;我错过了什么?

2 个答案:

答案 0 :(得分:3)

嗯," [类型]看起来非常相似"在编程中并不重要。

你缺少的是块和函数指针是不同类型的东西。

函数指针几乎就是函数代码第一条指令的地址。

块是一个对象。该对象持有的数据是函数指针,但它也有其他数据。除了作为对象的基本基础结构(例如isa指针)之外,块可以从其定义站点捕获变量值。

你可以在Objective-C中使用函数指针。如果您希望两个接口直接兼容,只需使用CALCULATION_CALLBACK作为Objective-C方法中callback参数的类型。

或者,您可以将函数指针包装在一个块中,如下所示:

void setCubeCallback(int x, CALCULATION_CALLBACK callback) {
    [[[IOSPluginTest alloc] init] cubeThisNumber:x andCallbackOn:^(int result){ callback(result); }];
}

答案 1 :(得分:1)

void(*)(int)是一个方法指针void(^)(int)一个块,在其他语言中称为闭包。它们根本不同。虽然方法指针只是这样做 - 指向一个方法 - ,但块也通过封装来传输数据。这个事情是非常不同的,尝试将它们从一个投射到另一个是没有意义的。

但是你可以在Objective-C中使用C方法指针。