|
Структура указателей. |
|
|
|
May 3 2015, 07:23
|
Профессионал
    
Группа: Участник
Сообщений: 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, ????, ???? }, }; Не могу никак сообразить как мне подставить указатель в команду (там где вопросительные знаки).
|
|
|
|
|
 |
Ответов
(1 - 14)
|
May 3 2015, 17:23
|
Знающий
   
Группа: Свой
Сообщений: 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]);
|
|
|
|
|
May 4 2015, 05:31
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
May 4 2015, 09:59
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
Можно сделать так CODE #include <stdint.h> #include <stdarg.h>
typedef uint32_t (*fp)(va_list ap);
// void (*fp1)(void); uint32_t fp1(va_list ap) { return 0; }
// void (*fp2)(uint32_t); uint32_t fp2(va_list ap) { uint32_t p1; p1 = va_arg(ap, uint32_t); return 0; }
// void (*fp3)(uint32_t, uint32_t); uint32_t fp3(va_list ap) { uint32_t p1, p2; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t); return 0; }
// void (*fp4)(uint32_t, uint32_t, uint32_t); uint32_t fp4(va_list ap) { uint32_t p1, p2, p3; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t); p3 = va_arg(ap, uint32_t); return 0; }
// uint32_t (*fp5)(uint32_t) uint32_t fp5(va_list ap) { uint32_t result = 0; uint32_t p1; p1 = va_arg(ap, uint32_t); result = p1 * p1; return result; }
// uint32_t (*fp6)(uint32_t, uint32_t); uint32_t fp6(va_list ap) { uint32_t result = 0; uint32_t p1, p2; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t);
result = p1 * p2; return result; }
uint32_t exec(fp f, ...) { va_list ap; uint32_t result; va_start(ap, f); result = f(ap); va_end(ap); return result; }
struct command { char *name; //command name
fp read_func_pointer; fp write_func_pointer; };
struct command commands[] = { {"gsm", fp1, fp2 }, {"ifb", fp3, fp4 }, {"bdsm", fp5, fp6 }, };
int main() { int res; uint32_t p1 = 1, p2 = 2, p3 = 3; // void (*fp1)(void); exec(commands[0].read_func_pointer); // void (*fp2)(uint32_t); exec(commands[0].write_func_pointer, p1); // void (*fp3)(uint32_t, uint32_t); exec(commands[1].read_func_pointer, p1, p2); // void (*fp4)(uint32_t, uint32_t, uint32_t); exec(commands[1].write_func_pointer, p1, p2, p3); // uint32_t (*fp5)(uint32_t) res = exec(commands[2].read_func_pointer, p1); // uint32_t (*fp6)(uint32_t, uint32_t); res = exec(commands[2].write_func_pointer, p1, p2); return res; }
|
|
|
|
|
May 4 2015, 10:30
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(desh @ May 4 2015, 14:59)  Можно сделать так CODE #include <stdint.h> #include <stdarg.h>
typedef uint32_t (*fp)(va_list ap);
// void (*fp1)(void); uint32_t fp1(va_list ap) { return 0; }
// void (*fp2)(uint32_t); uint32_t fp2(va_list ap) { uint32_t p1; p1 = va_arg(ap, uint32_t); return 0; }
// void (*fp3)(uint32_t, uint32_t); uint32_t fp3(va_list ap) { uint32_t p1, p2; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t); return 0; }
// void (*fp4)(uint32_t, uint32_t, uint32_t); uint32_t fp4(va_list ap) { uint32_t p1, p2, p3; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t); p3 = va_arg(ap, uint32_t); return 0; }
// uint32_t (*fp5)(uint32_t) uint32_t fp5(va_list ap) { uint32_t result = 0; uint32_t p1; p1 = va_arg(ap, uint32_t); result = p1 * p1; return result; }
// uint32_t (*fp6)(uint32_t, uint32_t); uint32_t fp6(va_list ap) { uint32_t result = 0; uint32_t p1, p2; p1 = va_arg(ap, uint32_t); p2 = va_arg(ap, uint32_t);
result = p1 * p2; return result; }
uint32_t exec(fp f, ...) { va_list ap; uint32_t result; va_start(ap, f); result = f(ap); va_end(ap); return result; }
struct command { char *name; //command name
fp read_func_pointer; fp write_func_pointer; };
struct command commands[] = { {"gsm", fp1, fp2 }, {"ifb", fp3, fp4 }, {"bdsm", fp5, fp6 }, };
int main() { int res; uint32_t p1 = 1, p2 = 2, p3 = 3; // void (*fp1)(void); exec(commands[0].read_func_pointer); // void (*fp2)(uint32_t); exec(commands[0].write_func_pointer, p1); // void (*fp3)(uint32_t, uint32_t); exec(commands[1].read_func_pointer, p1, p2); // void (*fp4)(uint32_t, uint32_t, uint32_t); exec(commands[1].write_func_pointer, p1, p2, p3); // uint32_t (*fp5)(uint32_t) res = exec(commands[2].read_func_pointer, p1); // uint32_t (*fp6)(uint32_t, uint32_t); res = exec(commands[2].write_func_pointer, p1, p2); return res; }
а как определен va_list ?
|
|
|
|
|
May 4 2015, 12:49
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
Цитата(Jenya7 @ May 4 2015, 14:08)  даже не знал что такой зверь существует  что то я туплю наверное - а где я передаю адресс своей функции? по моему я разобрался. мне придется переписать все свои функции а я хочу подставить готовую. что то теперь я затупил. чего там переписывать то? функцию вида Код void f(int a, int b, int c) { ... } привести к виду Код int f(va_list ap) { int a = va_arg(ap, int); int b = va_arg(ap, int); int c = va_arg(ap, int); ... return 0; } ?
|
|
|
|
|
May 4 2015, 13:03
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(desh @ May 4 2015, 17:49)  что то теперь я затупил. чего там переписывать то? функцию вида Код void f(int a, int b, int c) { ... } привести к виду Код int f(va_list ap) { int a = va_arg(ap, int); int b = va_arg(ap, int); int c = va_arg(ap, int); ... return 0; } ? у меня уже под 100 функций к тому же разбросанных по своим файлам.
|
|
|
|
|
May 4 2015, 13:10
|
Частый гость
 
Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725

|
ну тогда для особых любителей третьей команды можно сделать так CODE #include <stdint.h> typedef union { void (*fp1p)(void); void (*fp2p)(uint32_t); void (*fp3p)(uint32_t, uint32_t); void (*fp4p)(uint32_t, uint32_t, uint32_t); uint32_t (*fp5p)(uint32_t); uint32_t (*fp6p)(uint32_t, uint32_t); uint32_t (*fp7p)(uint32_t, uint32_t, uint32_t); } fp; void fp1(void) { } void fp2(uint32_t a) { } void fp3(uint32_t a, uint32_t  { } void fp4(uint32_t a, uint32_t b, uint32_t c) { } uint32_t fp5(uint32_t a) { return a * a; } uint32_t fp6(uint32_t a, uint32_t  { return a * b; } struct command { char *name; //command name fp read_func_pointer; fp write_func_pointer; }; struct command commands[] = { [0] = { "gsm", fp1, .write_func_pointer.fp2p = fp2 }, [1] = { "ifb", .read_func_pointer.fp3p = fp3, .write_func_pointer.fp4p = fp4 }, [2] = { "bdsm", .read_func_pointer.fp5p = fp5, .write_func_pointer.fp6p = fp6 }, }; int main() { int res; commands[0].read_func_pointer.fp1p(); commands[0].write_func_pointer.fp2p(1); commands[1].read_func_pointer.fp3p(1, 2); commands[1].write_func_pointer.fp4p(1, 2, 3); res = commands[2].read_func_pointer.fp5p(1); res = commands[2].write_func_pointer.fp6p(1, 2); return res; } будет компилиться начиная с C99
|
|
|
|
|
May 4 2015, 13:31
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(desh @ May 4 2015, 18:10)  ну тогда для особых любителей третьей команды можно сделать так CODE #include <stdint.h> typedef union { void (*fp1p)(void); void (*fp2p)(uint32_t); void (*fp3p)(uint32_t, uint32_t); void (*fp4p)(uint32_t, uint32_t, uint32_t); uint32_t (*fp5p)(uint32_t); uint32_t (*fp6p)(uint32_t, uint32_t); uint32_t (*fp7p)(uint32_t, uint32_t, uint32_t); } fp; void fp1(void) { } void fp2(uint32_t a) { } void fp3(uint32_t a, uint32_t  { } void fp4(uint32_t a, uint32_t b, uint32_t c) { } uint32_t fp5(uint32_t a) { return a * a; } uint32_t fp6(uint32_t a, uint32_t  { return a * b; } struct command { char *name; //command name fp read_func_pointer; fp write_func_pointer; }; struct command commands[] = { [0] = { "gsm", fp1, .write_func_pointer.fp2p = fp2 }, [1] = { "ifb", .read_func_pointer.fp3p = fp3, .write_func_pointer.fp4p = fp4 }, [2] = { "bdsm", .read_func_pointer.fp5p = fp5, .write_func_pointer.fp6p = fp6 }, }; int main() { int res; commands[0].read_func_pointer.fp1p(); commands[0].write_func_pointer.fp2p(1); commands[1].read_func_pointer.fp3p(1, 2); commands[1].write_func_pointer.fp4p(1, 2, 3); res = commands[2].read_func_pointer.fp5p(1); res = commands[2].write_func_pointer.fp6p(1, 2); return res; } будет компилиться начиная с C99 спасибо. сейчас попробую. у меня в ИАР выставлен диалект С99. большое спасибо. работает. что мне нравиться так это гибкость. всегда можно добавить в юнион недостающию функцию.
Сообщение отредактировал Jenya7 - May 4 2015, 14:08
|
|
|
|
|
May 4 2015, 19:12
|
Знающий
   
Группа: Свой
Сообщений: 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 - как пример второй команды. В случае управляющего терминала видимо команда должна сразу выдавать результат работы в выходной буфер последовательного порта, поэтому вот так.
|
|
|
|
|
May 5 2015, 06:21
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390

|
Цитата(Jenya7 @ May 5 2015, 08:15)  спасибо. у меня команда без аргумента показывает текущее значение, с аргументом записывает новое. поэтому два указателя на функции чтения и записи. обработку можно как в самой команде сделать в if(!args), так и в цикле поиска команды по имени: Код struct cmd { char* name; int (*cmd_read)(void); int (*cmd_write)(char** args); }; ... int test_read(){ return 0; } ... if(!strcmp(cmds[i].name, args[0])) { if(args[1]) cmds[i].cmd_write(&args[1]); else cmds[i].cmd_read(); }
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|