块的签名,它接受一个函数指针并返回一个块

时间:2018-05-09 03:53:09

标签: c clang objective-c-blocks

我在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的函数指针作为参数,并返回一个块,该块使用传递的参数调用该func。

3 个答案:

答案 0 :(得分:2)

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

#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将函数指针作为其参数,并返回带有签名int (^block)(int, char **)的块。

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

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

代码的输出是:

  

您好
  计数= 3

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

答案 1 :(得分:1)

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来帮助简化类型签名。我建议您在接受和/或返回函数指针/块指针时使用这些。

Block_copy()将块从堆栈移动到堆中。

保存从

返回的块指针更为正确
f2b(fake_main)

然后使用后调用

Block_release()

就可以了。

答案 2 :(得分:1)

您的类型语法不正确。根据您的使用情况,我猜测您声明f2b是指向块的指针,该指针指向一个指向intchar **的函数的指针。返回int,该块返回另一个带有intchar **的块,并返回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(他们说&#34;块&#34;而我说&#34;指向块&#34的指针;)

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

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);
    });
};

在块文字中可以省略返回类型,因此它可以写成:

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