jenya7 0 3 мая, 2015 Опубликовано 3 мая, 2015 · Жалоба У меня каждая команда принимаемая из терминала привязана к своей функции. Функции бывают разные - возвращающие значение, не возвращающие значение, с одним аргументом, двумя аргументами и так далее. Я решил собрать все мои функции в структуру и потом присваивать соответствующий указатель. 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, ????, ???? }, }; Не могу никак сообразить как мне подставить указатель в команду (там где вопросительные знаки). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 3 мая, 2015 Опубликовано 3 мая, 2015 · Жалоба У меня каждая команда принимаемая из терминала привязана к своей функции... Как уже отвечал в предыдущей теме, в вашей задаче проще парсить входящий буфер в массив указателей на подстроки. Тогда 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]); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 3 мая, 2015 Опубликовано 3 мая, 2015 · Жалоба в вашей задаче проще парсить входящий буфер в массив указателей на подстроки. Тогда arg[0] будет командой, а все остальные arg - ее параметры +1. Я тоже так делаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 мая, 2015 Опубликовано 4 мая, 2015 (изменено) · Жалоба Как уже отвечал в предыдущей теме, в вашей задаче проще парсить входящий буфер в массив указателей на подстроки. Тогда 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 *)" Изменено 4 мая, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба Можно сделать так #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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба Можно сделать так #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 ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба Посмотрите в stdarg.h. Он не укусит :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 мая, 2015 Опубликовано 4 мая, 2015 (изменено) · Жалоба Посмотрите в stdarg.h. Он не укусит :rolleyes: даже не знал что такой зверь существует :) что то я туплю наверное - а где я передаю адресс своей функции? по моему я разобрался. мне придется переписать все свои функции а я хочу подставить готовую. Изменено 4 мая, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба даже не знал что такой зверь существует :) что то я туплю наверное - а где я передаю адресс своей функции? по моему я разобрался. мне придется переписать все свои функции а я хочу подставить готовую. что то теперь я затупил. чего там переписывать то? функцию вида 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; } ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба что то теперь я затупил. чего там переписывать то? функцию вида 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 функций к тому же разбросанных по своим файлам. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба ну тогда для особых любителей третьей команды можно сделать так #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 B) { } 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 B) { 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 мая, 2015 Опубликовано 4 мая, 2015 (изменено) · Жалоба ну тогда для особых любителей третьей команды можно сделать так #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 B) { } 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 B) { 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. большое спасибо. работает. что мне нравиться так это гибкость. всегда можно добавить в юнион недостающию функцию. Изменено 4 мая, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 4 мая, 2015 Опубликовано 4 мая, 2015 · Жалоба то есть 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 - как пример второй команды. В случае управляющего терминала видимо команда должна сразу выдавать результат работы в выходной буфер последовательного порта, поэтому вот так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 5 мая, 2015 Опубликовано 5 мая, 2015 · Жалоба Для расширения функциональности нужно просто дописывать функцию и добавлять ее в таблицу команд cmds[] Пример разбора аргументов - в cmd_test, test2 - как пример второй команды. В случае управляющего терминала видимо команда должна сразу выдавать результат работы в выходной буфер последовательного порта, поэтому вот так. спасибо. у меня команда без аргумента показывает текущее значение, с аргументом записывает новое. поэтому два указателя на функции чтения и записи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
psL 0 5 мая, 2015 Опубликовано 5 мая, 2015 · Жалоба спасибо. у меня команда без аргумента показывает текущее значение, с аргументом записывает новое. поэтому два указателя на функции чтения и записи. обработку можно как в самой команде сделать в 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться