Get a pointer to the current function in C (gcc)?
gcc中是否有一个保存当前函数指针的魔力变量?
我想要一种表,其中为每个函数指针包含一组信息。
我知道有一个变量包含当前函数的名称作为字符串,而不是作为函数指针。
这不是调用函数,而是用作索引。
编辑基本上,我想做的是能够在当前函数执行之前运行嵌套函数(同时捕获返回以执行某些操作)。基本上,这就像uucyg_profile_func_enter和ucyg_profile_func_exit(仪器功能)。但问题是这些工具函数是全局的,而不是专用的函数。
编辑在Linux内核中,您可以使用
1 2 3 | void f() { void (*fpointer)() = &f; } |
1 | #define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__)) |
。
像这样编译你的程序
1 | gcc -rdynamic -o foo foo.c -ldl |
我认为您可以使用字符串(函数名)作为键来构建表,然后通过与
要强制使用有效的函数名,可以使用获取函数指针的宏,对其执行一些虚拟操作(例如,将其分配给兼容的函数类型临时变量),以检查它是否确实是有效的函数标识符,然后在用作键之前对函数名进行字符串化(使用)。
更新:
我的意思是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | typedef struct { char[MAX_FUNC_NAME_LENGTH] func_name; //rest of the info here } func_info; func_info table[N_FUNCS]; #define CHECK_AND_GET_FUNC_NAME(f) ({void (*tmp)(int); tmp = f; #f}) void fill_it() { int i = -1; strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(foo)); strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(bar)); //fill the rest } void lookup(char *name) { int i = -1; while(strcmp(name, table[++i])); //now i points to your entry, do whatever you need } void foo(int arg) { lookup(__func__); //do something } void bar(int arg) { lookup(__func__); //do something } |
(代码可能需要一些修改,我没有试图编译它,只是为了说明这个想法)
这是一个获取调用者地址的技巧,它可能会被清除一点。依赖GCC扩展来获取标签的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h> #define MKLABEL2(x) label ## x #define MKLABEL(x) MKLABEL2(x) #define CALLFOO do { MKLABEL(__LINE__): foo(&&MKLABEL(__LINE__));} while(0) void foo(void *addr) { printf("Caller address %p ", addr); } int main(int argc, char **argv) { CALLFOO; return 0; } |
。
如果你选择C++,下面的信息可能会帮助你:
对象被类型化,函数被包装为对象,rtti允许在运行时标识类型。
函数会带来运行时开销,如果这对您来说是个问题,我建议使用代码生成或利用函数的OO继承性对知识进行硬编码。
埃多克斯1〔5〕
如果您想生成代码,我建议您从IMATIX中修改GSLGen。它使用XML来构建代码模型,然后使用一种简单的类似于PHP的自顶向下生成语言来输出代码——它被用来生成C代码。
我个人一直在玩弄Lua来生成代码。
您可以使用
这个结构是高度不可移植的,但是您明确地提到了GCC,所以这可能不是一个阻塞问题。请参阅这个gcc/x86示例,了解它的大致工作原理。
如果你想用一种"通用"的方式来做这件事,那么你应该使用你已经提到过的设施(
老实说,用常规方法(使用过滤器)进行操作可能比您将要即时插入的任何新方法都不容易出错。
不,函数本身不知道。您必须构建您正在谈论自己的表,然后如果您想要一个函数了解它自己,您必须将索引作为参数传递到全局表(或函数的指针)中。
注意:如果您想这样做,您应该有一个一致的参数命名方案。
如果可移植性不是一个问题,另一个选择是调整gcc源代码…有志愿者吗?!
如果您所需要的只是每个函数的唯一标识符,那么在每个函数的开头,请将其放在:
1 | static const void * const cookie = &cookie; |
号
然后保证EDOCX1的值(0)是唯一标识该函数的值。