测试代码:
void print1()
{
printf("functon1 printing\n");
}
//I can add other function like:
void print2()
{
printf("function 2 printing\n");
}
// Is there a way when I call print1 in main, actually print2 works?
// I mean if print2 exist , main use print2 . else use print1.
// Hope no macro answer , any gcc attribute way is best! For I want use it in more complex code.
int main()
{
print1();
return 0;
}
这里我希望程序打印另一个字符串,如:“function 2 is printing”。
注意: 在某些情况下,我无法更改主要功能和print1功能!!
我希望有一种方法可以使用涵盖function1
的其他功能并打印我的字符串。
我使用GCC,我对_ 属性 _知之甚少。但是,我认为gcc可以做到这一点。
是否有可能:
any gcc attribute way is best! For I want use it in more complex code.
或者它只是gcc属性不能那样做?
有谁能举个例子?
谢谢。
答案 0 :(得分:2)
如果您无法修改print1()
和main()
之间的任何内容,则可以更改print1()
对宏执行的操作:
void nada (const char *s) {}
#define printf puts("function2 printing"); nada
如果允许在print1()
和main()
之间添加代码,则可以定义新函数,然后使用宏将print1
定义为新函数。
您提出的问题是,您对解决方案的强加要求限制了解决问题的方法数量。
print1()
无法修改。print1()
中main()
的调用方式无法修改。所有这些限制使得难以为您的问题提供一个很好的灵活解决方案,这就是您获得这些宏风格解决方案的原因。请允许我描述一些不受这些限制的解决方案。
创意#1:在要覆盖的功能上使用weak
属性。然后,重新定义print1()
以检查是否存在覆盖:
extern void print2 () __attribute__((weak));
void print1 ()
{
if (print2) { print2(); return; }
puts("function1 printing");
}
由于print2()
是使用weak
属性声明的,因此您可以测试是否存在其定义。如果是,print1()
会调用它而不是按照通常的方式执行。
这允许您将所有函数定义保留在同一源文件中,但您需要修改print1()
。
提示2:将print1()
与main()
分隔为单独的文件。使用链接器的-wrap print1
选项使程序将对象中的print1
解析为符号__wrap_print1
。使用此选项时,对符号__real_print1
的引用将解析为原始print1
,但此解决方案不需要该功能。
$ cat main.c
extern void print1 ();
int main ()
{
print1();
}
$ cat print.c
#include <stdio.h>
void print1 () { puts("function1 printing"); }
void print2 () { puts("function2 printing"); }
void __wrap_print1 () { print2(); }
$ gcc main.c print.c && ./a.out
function1 printing
$ gcc -Wl,-wrap,print1 main.c print.c && ./a.out
function2 printing
您根本不需要修改print1()
,但可以在与print2()
相同的文件中定义print1()
,除非重新编译,否则覆盖不会生效。< / p>
创意3:如果print1()
位于共享库中,您可以使用另一个定义print1()
备用版本的共享库来覆盖原始定义。您可以使用LD_PRELOAD
按需加载此不同的共享库。
gcc main.c -o print1_test -lprint1
gcc -fPIC -c newprint1.c
gcc -shared -o newprint1.so newprint1.o
LD_PRELOAD=./newprint1.so ./print1_test
对于此解决方案,print1()
不仅需要位于不同的源文件中,还需要将其编译为共享对象并进行链接。新的print1()
覆盖驻留在不同的源文件中,并编译到不同的共享库中。但是,覆盖不需要重新编译。
答案 1 :(得分:2)
这是一个黑客攻击,但唯一可移植(并且非常合理)的方法是使用宏预处理器。
定义print1
后,定义print2
:
void print2(void) { printf("function 2 is printing.\n"); }
然后,在main
之前,使用#define
将print1
替换为print2
:
#define print1 print2
请注意,生产代码中的合法用途很少。它在调试时偶尔会有用。您还偶尔会看到它重新定义像malloc
这样的stdlib函数。它仍然是一个黑客,应该避免。
答案 2 :(得分:1)
为了隐藏一个函数,就像在现有函数周围包装自己的函数而不替换原始函数的名称一样,请参阅我对此主题的另一个答案:https://stackoverflow.com/a/17191529/694576