将一个函数指针"转换"为objective-C中的一个块

Ami*_*oaf 10 function-pointers block objective-c objective-c-blocks

我正在做一些从Mono C#到Obj-C的Interop并遇到了这个问题.C#代码需要传递回调 - 它与函数指针一起执行.我可以从Obj-C端获取函数指针并调用它,一切正常.但我现在需要将该函数指针作为对第三方API的回调,该第三方API将块作为回调.我希望第三方调用C#函数 - 所以在某种程度上我试图将函数指针转换为块,以便第三方可以运行它,或者创建某种桥 - 创建我自己的块运行该函数指针并将其提供给第三方.我似乎无法找到一种方法 - 如何生成一个块,其中包含运行哪个函数的信息,然后将其提供给第三方.也许还有另一种选择吗?

编辑:将函数放在一个全局变量可能会有效,但我希望能够拥有大量的函数,因为第三方API是异步的,我不希望它调用错误的回调.

我试过的代码:

typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);

@interface FunctionToBlock : NSObject
{
    DummyAction function;
    DummyBlock block;
}

- (id) initWithFunction: (DummyAction) func;
- (DummyBlock) block;
@end

@implementation FunctionToBlock : NSObject
- (id) initWithFunction: (DummyAction) func {
    if (self = [super init]) {
        function = func;
        block = ^(char * result) {
            function(result);
        };
    }
    return self;
}

- (DummyBlock) block {
    return block;
}
@end
Run Code Online (Sandbox Code Playgroud)

然后我运行它

void RegisterCallback( char * text, DummyAction callback)
{
    FunctionToBlock *funcToBlock = [[FunctionToBlock alloc] initWithFunction : callback];
    funcToBlock.block(text);
}
Run Code Online (Sandbox Code Playgroud)

它失败了BAD_ACCESS.也许我做错了,因为我对Obj-C还不是很熟练.如果直接运行并且正在调用块但是它在函数(结果)行上失败,我可以确认回调是可以的.

Mar*_*n R 6

关于什么

void (*myFunc)(int x); // ... your function pointer

void (^myBlock)(int) = ^(int x) {
    myFunc(x);
};
Run Code Online (Sandbox Code Playgroud)

然后myBlock是一个块,它捕获函数指针的值,并在执行块时调用该函数.


补充:我的建议,基于您的代码,使用@property(假设您使用ARC编译):

FunctionToBlock.h:

typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);

@interface FunctionToBlock : NSObject
{
    DummyAction function; // Not really needed.
}

- (id) initWithFunction: (DummyAction) func;
@property(copy, nonatomic) DummyBlock block;   // "copy" is important here!

@end
Run Code Online (Sandbox Code Playgroud)

FunctionToBlock.m:

#import "FunctionToBlock.h"

@implementation FunctionToBlock : NSObject
@synthesize block = _block; // Can be ommitted if you use Xcode 4.4 or later.

- (id) initWithFunction: (DummyAction) func
{
    if (self = [super init]) {
        function = func; // Not really needed.
        self.block = ^(char * result) {
            func(result); // Use "func", not "self->function", to avoid retain cycle.
        };
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)


new*_*cct 6

为什么不只是有一个简单的功能

typedef void (*DummyAction)(char * result);
typedef void (^DummyBlock)(char * result);

DummyBlock functionToBlock(DummyAction func) {
    return [[^(char * result) {
                 func(result);
             } copy] autorelease];
}
Run Code Online (Sandbox Code Playgroud)