Outline:
1. 如何从函数指针获得函数名?
2. 函数指针结构必须与函数同构。
3. 当函数指针作为另一个函数的参数时,另一个函数的该参数不能简单的是指针参数,而应该是整个函数指针定义。这样这个参数才能表面自己是个函数指针,而不是其他普通指针。
函数指针可以使状态机编程变得简单,但是同时由于函数指针并不是显示调用函数,在debug程序时可能会增加很多问题。
如何从函数指针获得函数名
http://stackoverflow.com/questions/351134/how-to-get-functions-name-from-functions-pointer-in-c
在这个帖子中,大牛们提供了不少方法,
要么需要编译时加参数,这在已成型的编译复杂产品不可用。不过一个提示是在以后debug版本时加上该参数 –rdynamic
#include <stdio.h> #include <execinfo.h> void foo(void) { printf("foo\n"); } int main(int argc, char *argv[]) { void *funptr = &foo; backtrace_symbols_fd(&funptr, 1, 1); return 0; }
Compile with
gcc test.c –rdynamic
output
./a.out
(foo+0x0)[0x8048634]
要么在调用函数中直接加log。这个方法最简单,但是最麻烦,当很多函数都被函数指针指向时,可能涉及多个文件多个函数,不仅仅是修改麻烦,更重要的是debug版本控制也会增加额外effort.
还有一种方法是使用printk
void *func = &foo; printk("func: %pF at address: %p\n", func, func);
但是这种方法我并没有试验成功.
最后,我采用了一种用if实现的简单的map方式,实现指正名查询。好处是可以只修改一个文件便获得函数名。缺点是还是麻烦
#include <stdio.h> #include <string.h> int test_fun(char* str) { printf("test_fun inside: %s\t", str); return 1; } int ignor_fun(char* str) { printf("ignor_fun inside: %s\t", str); return 1; } int getFuncName(int (*funptr)(char* str) , char * funname) // 函数指针作为参数,该参数必须写完这个函数指针定义int (*funptr)(char* str), 而不是简单是int (*funptr)。 这样编译器才知道该函数是一个函数指针,而非普通变量指正。 { if (funptr == NULL) strcpy(funname, "NULL"); else if (funptr == test_fun) strcpy(funname, "test_fun"); else strcpy(funname, "UNKNOWN"); if (funptr != NULL) (*funptr)(funname); //正因为参数里声明是指数参数,才可以做函数调用。 } int main(int argc, char *argv[]) { int (*funptr)(char* str) ; char funname[50] = "UNKNOWN"; printf ("1: %p\t", funptr); getFuncName(funptr,funname); printf("find output: %s\n", funname); funptr = test_fun; printf ("2: %p\t", funptr); getFuncName(funptr,funname); printf("find output: %s\n", funname); funptr = ignor_fun; printf ("3: %p\t", funptr); getFuncName(funptr,funname); printf("find output: %s\n", funname); return 1; }
编译并运行
gcc test.c
./a.out
1: (nil) find output: NULL
2: 0x400504 test_fun inside: test_fun find output: test_fun
3: 0x400530 ignor_fun inside: UNKNOWN find output: UNKNOWN
在这个例子中,提供一个外部函数 int getFuncName(int (*funptr)(char* str) , char * funname) 查询当前函数名。
由于这个外部查询函数中,函数指针是一个函数传入,因此不能同构。