Подпись блока для блока, который принимает указатель на функцию и возвращает блок - PullRequest
0 голосов
/ 09 мая 2018

Я использую Clang на Linux. Как правильно отформатировать этот блок?

(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 в качестве параметра и возвращает блок, который вызывает этот функционал, используя переданные им аргументы.

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

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

Это минимальный пример достижения целей, которые я изложил в этом вопросе.

Хитрость в typedefs. Упростите сигнатуру типа, создавая typedefs, чтобы помочь. Я рекомендую использовать их всякий раз, когда вы хотите принять и / или вернуть указатель на функцию / указатель на блок.

Block_copy () перемещает блок из стека в кучу.

Было бы правильнее сохранить указатель блока, возвращенный из

f2b(fake_main)

Тогда после использования звоните

Block_release()

На это.

0 голосов
/ 28 мая 2018

Ваш синтаксис типа неверен. Исходя из вашего использования, я предполагаю, что вы объявляете f2b указателем на блок, который берет указатель на функцию, которая принимает int и char ** и возвращает int, и блок возвращает другой блок, который принимает int и char ** и возвращает int.

Правильный синтаксис для этого объявления:

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

Синтаксис для более сложных типов C часто нелогичен, особенно в случае нескольких уровней функций и массивов.

Всегда полезный веб-сайт cdecl.org поддерживает блоки: объявляет f2b как блок (указатель на функцию (int, указатель на указатель на char), возвращающий int), возвращающий блок (int, указатель на указатель на char), возвращающий int (они говорят «блок», тогда как я говорю «указатель на блок»)

Ваше определение блока, записанное с использованием полного литерального синтаксиса блока (включая возвращаемые типы), будет выглядеть примерно так (не забудьте скопировать блок для его возврата):

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);
    });
};
0 голосов
/ 09 мая 2018

Ключом является функция Block_copy из <Block.h> 1 . Это помещает копию блока в кучу, что позволяет вернуть блок.

#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 Я не знал о <Block.h> до прочтения ответа ОП.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...