采用函数指针和 returns 块的块的块签名

Block signature for block that takes a function pointer and returns a block

我在 linux 上使用 clang。 格式化此块的正确方法是什么?

(int ^(int, char**)) (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))
{
  return int ^(int argc, char** argv){ func(argc, argv)};
};

我收到一个错误

error: type-id cannot have a name int (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))

错误下划线 (*func)。

我正在尝试创建一个块,该块接受一个名为 func 的函数指针作为参数,returns 一个块使用传递的参数调用该 func。

关键是 <Block.h>1 中的 Block_copy 函数。这会在堆上放置一个块的副本,从而允许返回该块。

#include <stdio.h>
#include <Block.h>

typedef int (^block_t)(int, char **);
typedef int (*func_t)(int, char **);

block_t (^createBlock)(func_t func) = ^(func_t func)
{
    return Block_copy( ^(int argc, char **argv) { return func(argc, argv); } );
};

int showFirst(int argc, char *argv[])
{
    printf("%s\n", argv[0]);
    return argc;
}

int main(void)
{
    int argc = 3;
    char *argv[] = {"hello", "world", NULL};

    block_t block1 = createBlock(showFirst);
    int count = block1(argc, argv);
    printf("count=%d\n", count);
    Block_release(block1);
}

createBlock 将函数指针作为其参数,returns 一个带有签名 int (^block)(int, char **) 的块。

showFirst 只是可以传递给 createBlock 的函数的一种可能实现。它显示 argv 数组中的第一个字符串和 returns argc 中的值。

main 函数从 showfirst 函数创建一个块。然后调用块,打印返回值,然后释放块。

代码的输出是:

hello
count=3


1 在阅读 OP 的回答之前我不知道 <Block.h>

http://thirdcog.eu/pwcblocks/帮了大忙。

#include <stdlib.h>
#include <stdio.h>
#include <Block.h>

int fake_main(int argc, char** words)
{
  printf("%s\n", (char*)words);
  return argc;
}

int main(int argc, char* argv[])
{
  typedef int(*main_type_func)(int, char**);
  typedef int(^main_type)(int, char**);
  typedef main_type(^f2b_type)(main_type_func);

  f2b_type f2b = ^ (main_type_func func)
    {
      return Block_copy(^ (int apple, char** ban)
      {
        return func(apple, ban);
      });
    };

  printf("%d\n", f2b(fake_main)(1, "words worked"));
}

这是实现我在问题中概述的目标的最小示例。

诀窍在于 typedef。通过创建 typedef 来帮助简化类型签名。我建议您在想要接受 and/or return 函数 pointer/block 指针时使用这些。

Block_copy() 将块从栈移入堆。

保存块指针return来自

会更正确
f2b(fake_main)

然后使用后调用

Block_release()

在上面。

您的类型语法不正确。根据你的用法,我猜你是在声明 f2b 是一个指向块的指针,它接受一个指向一个函数的指针,该函数接受一个 int 和一个 char ** 和 return 是一个 int,块 return 是另一个块,它采用 intchar ** 并且 return 是 int .

该声明的正确语法是:

int (^(^f2b)(int (*) (int, char **)))(int, char **)

更复杂的 C 类型的语法通常是违反直觉的,尤其是在多级函数和数组的情况下。

非常有用的 cdecl.org 网站支持块:declare f2b as block(pointer to function(int, pointer to pointer to char) returning int) returning block(int, pointer to pointer to char) returning int(他们说 "block" 而我说 "pointer to block")

使用完整的块文字语法(包括 return 类型)写出的块定义将是这样的(记得复制块以便 return 它):

int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^int (^(int (*func)(int, char **)))(int, char **) {
    return Block_copy(^int (int argc, char **argv) {
        return func(argc, argv);
    });
};

Return 类型可以在块字面量中省略,因此可以这样写:

int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^(int (*func)(int, char **)) {
    return Block_copy(^(int argc, char **argv) {
        return func(argc, argv);
    });
};