能否直接将函数指针作为块参数传递?

8

假设我有一个需要一个块的函数:

void foo(Foo (^block)(Bar));

假设我有一个与该函数具有相同签名的函数,只不过它不是一个块:

Foo myFunction(Bar);

我可以做到这一点:


foo(^(Bar bar) { return myFunction(bar); });

但是如果这个方法可行的话,我更愿意使用以下方式:

foo(&myFunction);

如果我尝试这样做,XCode会提示:

No matching function for call to 'foo'

块是一个函数指针和一些上下文的组合,因此在这个层面上,使用一个空上下文的纯函数指针作为块似乎是合理的。这是否可行?


一个块不是带有上下文的函数指针。它是指向上下文的指针,这个上下文碰巧包含了一个函数指针。 - ughoavgfhw
即便如此,似乎让语言在上下文中仅包含给定的函数指针而不包含其他内容是微不足道的。但我猜这还没有被实现。(也许需要类似C++的重载才能变得合理)。这并不是一个很大的问题。 - glaebhoerl
这并不是一件简单的事情;你必须能够将上下文的引用传递到函数中,以便函数体能够检索该上下文--以检索捕获的变量。重载是无济于事的。 - bbum
3个回答

9

一个 block 是一个函数指针加上一些上下文,因此在这个层面上,希望使用一个空上下文的普通函数指针作为 block 看起来是合理的。但这是否可能呢?

然而,问题在于 block 不是 一个函数指针加上一些上下文

一个 block 在编译期间捕获可执行代码和执行状态。该可执行代码遵循 C ABI 以传递参数,但是,与方法调用类似,它具有一些非常特定的要求。将其转换为 C 函数声明,返回一个 BOOL 并带有单个 int 参数的 block 如下所示:

BOOL blockLikeFunc(void *block, int arg) { ... }

也就是说,块的“函数”的第一个参数必须是指向块本身的指针。

因此,不能仅仅提取块的“函数”指针并将其强制转换为C函数。


0
@import Foundation;

@implementation NSObject(extra)
+ (int)callFunction:(int (^)(int))function withArgument:(int)arg
{
    return function(arg);
}
@end;

int main() {
    @autoreleasepool {
        NSLog(@"doubleIt(3) returns %d", [NSObject callFunction:^(int param) { return param * param; } withArgument:3]);
    } return 0;
}

0
“但是一个块是一个函数指针”。 除了它不是。如果你想把一个函数指针作为参数传递,试试这个:
int FooDouble(int x)
{
    return x * 2;
}

- (int)callFunction:(int (*)(int))function withArgument:(int)arg
{
    return function(arg);
}

NSLog(@"%d", [self callFunction:FooDouble withArgument:21]);

这将输出 42


“一个块是函数指针”和“一个块是带有一些上下文的函数指针”并不意味着相同的事情。我说的是后者。而且我知道如何使用函数指针。谢谢。 - glaebhoerl
@illissius 在这种情况下,你有什么问题? - user529758

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接