реклама на сайте
подробности

 
 
> Структура указателей.
Jenya7
сообщение May 3 2015, 07:23
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



У меня каждая команда принимаемая из терминала привязана к своей функции. Функции бывают разные - возвращающие значение, не возвращающие значение, с одним аргументом, двумя аргументами и так далее.
Я решил собрать все мои функции в структуру и потом присваивать соответствующий указатель.
Код
typedef struct
{
    void (*fp1)(void);
    void (*fp2)(uint32_t);
    void (*fp3)(uint32_t, uint32_t);
    void (*fp4)(uint32_t, uint32_t, uint32_t);
    uint32_t (*fp5)(uint32_t);
    uint32_t (*fp6)(uint32_t, uint32_t);
    uint32_t (*fp7)(uint32_t, uint32_t, uint32_t);
    //uint32_t (*fp5)(double x, double p[], double c);
} fp;

struct command
{
    char *name;  //command name
    uint32_t minargs;
    uint32_t maxargs;
    uint32_t minval;
    uint32_t maxval;
    //uint32_t return_type;
    //void *varp;  //return pointer to variable
    fp read_func_pointer;
    fp write_func_pointer;
};

struct command commands[] = {
    {"gsm", 1, 2,  0,  0,  ???? , ???? },
    {"ifb",   0,  1,  0,  0,  ????, ???? },
    
};

Не могу никак сообразить как мне подставить указатель в команду (там где вопросительные знаки).
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
psL
сообщение May 3 2015, 17:23
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Цитата(Jenya7 @ May 3 2015, 10:23) *
У меня каждая команда принимаемая из терминала привязана к своей функции...


Как уже отвечал в предыдущей теме, в вашей задаче проще парсить входящий буфер в массив указателей на подстроки. Тогда arg[0] будет командой, а все остальные arg - ее параметры
Т.е. в результате должно получиться как-то так:
Код
struct cmd {
  char* name;
  void* (*proc)(void*);
};

void* cmd1_proc(char** arg)
{
  while(NULL != *arg++){
    ..
  }
}

scruct cmd cmds[]={
  { .cmd="cmd1", .proc=cmd1_proc }, ..
}

  ..
    if(strcmp(arg[0], cmds[i].name))
       cmds[i].proc(&arg[1]);

Go to the top of the page
 
+Quote Post
Jenya7
сообщение May 4 2015, 05:31
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(psL @ May 3 2015, 22:23) *
Как уже отвечал в предыдущей теме, в вашей задаче проще парсить входящий буфер в массив указателей на подстроки. Тогда arg[0] будет командой, а все остальные arg - ее параметры
Т.е. в результате должно получиться как-то так:
Код
struct cmd {
  char* name;
  void* (*proc)(void*);
};

void* cmd1_proc(char** arg)
{
  while(NULL != *arg++){
    ..
  }
}

scruct cmd cmds[]={
  { .cmd="cmd1", .proc=cmd1_proc }, ..
}

  ..
    if(strcmp(arg[0], cmds[i].name))
       cmds[i].proc(&arg[1]);

то есть
Код
void* (*proc)(void*);

это генерик указатель? Я могу подставить любую функцию?

при подстановке получаю:
Error[Pe144]: a value of type "uint32_t (*)(uint32_t, uint32_t)" cannot be used to initialize an entity of type "void *(*)(void *)"

Сообщение отредактировал Jenya7 - May 4 2015, 05:39
Go to the top of the page
 
+Quote Post
psL
сообщение May 4 2015, 19:12
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Цитата(Jenya7 @ May 4 2015, 08:31) *
то есть
Код
void* (*proc)(void*);

это генерик указатель? Я могу подставить любую функцию?

Нет. Эта функция в таком виде в данном конкретном случае не нужна.
Нужно вот так, с некоторыми оговорками:
Код
//char cmd[] = "test";//   arg1      arg2";
//char test[] = "test         arg1      arg2";
char test[] = "test2";

struct cmd {
    char* name;
    int (*cmd)(char** args);
};

int cmd_test(char** args)
{
    enum {
        ARG1=1,
        ARG2=2
    };
    int argc=ARG1;

    printf("CMD test,");

    if(!args)
    {
        printf("required parameters!\n");
        return -1;
    }

    do
    {
        switch(argc++)
        {
        case ARG1:
            printf(" ARG1: %s", *args);
            break;

        case ARG2:
            printf(" ARG2: %s", *args);
            break;

        default:
            printf("Unknown param: %s\n", *args);
            break;
        }

    }
    while(*++args);

    printf("\n");

    return 0;
}

int cmd_test2(char** args)
{
    printf("CMD test2\n");

    return 0;
}

struct cmd cmds[] =
{
    { .name = "test",   .cmd = cmd_test  },
    { .name = "test2",  .cmd = cmd_test2 },
};

int main ()
{
    int argc, i;

    argc = parse_command(test, args);

    for(i=0;i<sizeof(cmds)/sizeof(struct cmd); i++)
    {
        if(!strcmp(cmds[i].name, args[0]))
            cmds[i].cmd(args[1]?&args[1]:NULL);
    }

    return 0;
}


Для расширения функциональности нужно просто дописывать функцию и добавлять ее в таблицу команд cmds[]
Пример разбора аргументов - в cmd_test, test2 - как пример второй команды.
В случае управляющего терминала видимо команда должна сразу выдавать результат работы в выходной буфер последовательного порта, поэтому вот так.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 00:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.014 секунд с 7
ELECTRONIX ©2004-2016