如何在C中包装现有函数

时间:2017-04-03 11:08:35

标签: c wrapper

我正在尝试包装现有的功能。

下面的代码是完美的工作。

#include<stdio.h>

int __real_main();

int __wrap_main()
{
    printf("Wrapped main\n");
    return __real_main();
}

int main()
{
    printf("main\n");
    return 0;
}

命令:

gcc main.c -Wl,-wrap,main

输出:

Wrapped main
main

所以我用temp改变了主要功能。我的目标是包装temp()函数。

以下是代码

temp.c

#include<stdio.h>

int temp();

int __real_temp();

int __wrap_temp()
{
    printf("Wrapped temp\n");
    return __real_temp();
}

int temp()
{
    printf("temp\n");
    return 0;
}

int main()
{
    temp();
    return 0;
}

命令:

gcc temp.c -Wl,-wrap,temp

输出:

temp

包裹的温度不打印。请引导我包装funciton temp。

2 个答案:

答案 0 :(得分:6)

ld的联机帮助页说:

   --wrap=symbol
       Use a wrapper function for symbol.  Any undefined reference to symbol will be resolved to "__wrap_symbol".  Any
       undefined reference to "__real_symbol" will be resolved to symbol.

此处的关键字未定义。

如果将定义temp放在与使用它的代码相同的翻译单元中,则在使用它的代码中不会定义它。

您需要拆分代码定义和使用它的代码:

#!/bin/sh

cat > user.c  <<'EOF'
#include<stdio.h>

int temp(void);

int __real_temp(void);

int __wrap_temp()
{
    printf("Wrapped temp\n");
    return __real_temp();
}
int main()
{
    temp();
    return 0;
}
EOF

cat > temp.c <<'EOF'
#include<stdio.h>
int temp()
{
    printf("temp\n");
    return 0;
}
EOF


gcc user.c  -Wl,-wrap,temp temp.c  # OK
./a.out

将构建拆分为两个单独的编译可能会更清楚:

$ gcc -c user.c
$ gcc -c temp.c
$ nm user.o temp.o

temp.o:
                 U puts
0000000000000000 T temp

user.o:
0000000000000015 T main
                 U puts
                 U __real_temp
                 U temp
0000000000000000 T __wrap_temp

由于tempuser.c未定义,因此链接器可以对其执行__real_ / __wrap_魔术。

$ gcc  user.o temp.o  -Wl,-wrap=temp
$ ./a.out
  Wrapped temp
  temp

答案 1 :(得分:4)

如果您可以从要调用它的函数中拆分要覆盖的函数,PSCocik提出的答案效果很好。但是,如果要将被调用者和调用者保持在同一源文件中,--wrap选项将不起作用。

相反,您可以在实施被调用者之前使用__attribute__((weak)),以便让某人重新实现它而不会让GCC对多个定义大喊大叫。

例如,假设您要在以下 hello.c 代码单元中模拟world函数。您可以添加属性以便能够覆盖它。

#include "hello.h"
#include <stdio.h>

__attribute__((weak))
void world(void)
{
    printf("world from lib\n");
}

void hello(void)
{
    printf("hello\n");
    world();
}

然后您可以在另一个单元文件中覆盖它。对于单元测试/模拟非常有用:

#include <stdio.h>
#include "hello.h"

/* overrides */
void world(void)
{
    printf("world from main.c"\n);
}

void main(void)
{
    hello();
    return 0;
}