将块传递给纯 C 函数所需的语法是什么?

What is the required syntax to pass a block to a pure C function?

我有一个纯 C 函数,我想向其传递一个块(一个闭包?)。根据 Apple,块应该始终是函数的最后一个参数。

double pureCfunctionWithABlockParameter( int ignore, double ignore2, void (^myVoidBlockWithoutParameters)(void) ) {

myVoidBlockWithoutParameters(); /

return 0.0;    
}

接下来是Objective C调用C函数的代码:

- (void) testBlockFunctionality {

声明并定义块:

   void (^myBlock1)(void) ;

    myBlock1=^(void){ NSLog(@"myBlock1 just logs this message to the console");}; 

尝试直接调用块,不带括号。这是行不通的。 Xcode 警告 结果未使用 。 Block 的消息 记录到控制台。

    myBlock1;   

现在尝试直接调用块,这次用括号。这按预期工作。没有 Xcode 警告,块的消息被记录到控制台。

    myBlock1(); 

现在调用函数,将块作为参数传递,不带括号。这按预期工作,但语法与之前的块调用不一致。

    double someNumber;
    someNumber= pureCfunctionWithABlockParameter(0, 1, myBlock1 );     

现在调用该函数,再次将块作为参数传递,这次使用括号。这不起作用,它甚至不会编译,因为 Xcode 给出了一个:"Passing 'void' to parameter of incompatible type 'void (^)(void)'" 消息。

    someNumber= pureCfunctionWithABlockParameter(0, 1, myBlock1());   

最后,我实际上希望定义一个块来传递一个 int 参数,如下所示:

void(^block)(int)

但由于我认为是语法问题,我无法继续进行。

我查看了 Apple 的块编程主题,甚至是 K&R C,但没有运气。

这个问题引起了一些混乱,因为块(在问题的意义上)不是标准 C 的特性。Apple 在将它们添加到 Objective C 时将它们作为其 C 和 C++ 编译器的扩展添加,但它们不是 Apple 生态系统之外的 C 事物。我承认我没有实际使用它们的经验,但据我从文档中得知,例如 these,选择的语法与 C、C++ 和 [=57 相同=].事实上,一些消息来源声称语法的细节是专门选择的,以避免与 C++ 发生冲突的可能性。

从 C 的角度来看,接受一个块作为参数并调用以这种方式接收的块完全类似于分别接受函数指针和调用 pointed-to 函数。您的示例 C 函数似乎是正确的。

类似地适用于在所有三种语言中声明和使用块——它类似于声明和使用函数指针。我相信这是有意的设计考虑。于是

   void (^myBlock1)(void) ;

确实将 myBlock1 声明为不带参数且不返回任何内容的块,但未定义其值。 OP 观察到,在别处为其设置了有效值(如问题中所示)

Attempt to invoke the block directly, without parentheses. This doesn't work. Xcode warns result is unused. Block's message is NOT logged to console.

    myBlock1;

,这确实是意料之中的事情。这是一个语句表达式,计算块的值,而不是执行块的结果。它类似于

int myInt = 1;

myInt;  // specifically, analogous to this

要执行一个块,在括号中提供一个后缀参数列表(即使该列表为空),就像通过函数指针调用函数时一样:

Now attempt to invoke the block directly, this time with parentheses. This works as intended. No Xcode warnings, and the block's message IS logged to console.

    myBlock1();

参数列表的存在与否可以消除是访问块的值还是调用它的歧义。

混淆是关于将块传递给函数(或方法):

Now call the function, passing the block as parameter, WITHOUT parentheses. This works as intended, but the syntax is not consistent with the previous invocation of the block.

    double someNumber;
    someNumber= pureCfunctionWithABlockParameter(0, 1, myBlock1 );

然而,与问题中的断言相反,该语法完全一致,在内部与块语法和用法的其他方面一致,并且与类似的函数指针语法和用法一致。它将 传递给函数,通过名称识别块。块本身被传递,而不是执行它的结果,因为没有提供它的参数列表。

At the end of it all, I am actually looking to have a block defined that gets passed an int parameter, like this:

void (^block)(int)

But I cannot progress to that because of what I think is a syntax issue.

接受和使用此类块的 C 函数可能如下所示

void pass_2(void (^do_something)(int)) {
    do_something(2);
}

给定如上所示声明的变量 block,并分配一个有效块作为其值,该函数可以这样调用:

pass_2(block);

正如我们认识到函数 pass_2 是通过参数列表的存在来调用的,我们认识到变量 block 的值是作为参数传递的——而不是调用—— 缺少 参数列表。