【问题标题】:How to wrap existing function in C如何在 C 中包装现有函数
【发布时间】:2017-08-28 05:26:54
【问题描述】:

我正在尝试包装现有函数。

以下代码完美运行。

#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 更改了 main 函数。我的目标是包装 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

包装温度不打印。请指导我包装功能温度。

【问题讨论】:

  • 如果你想使用这个链接器,你必须将temp()移动到其他翻译单元(.c文件)。
  • 你还没有定义__real_temp()。但无论如何,不​​要做这种晦涩难懂的事情,这绝不是一个好主意。
  • user3188346 感谢哥们,它的工作非常感谢
  • @Lundin 不需要定义 __real_temp,链接器会这样做。此功能对于检测没有可用源的第三方代码非常方便。
  • 是否可以封装静态函数?

标签: c wrapper


【解决方案1】:

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

现在由于user.c 中的temp 未定义,链接器可以对其进行__real_/__wrap_magic。

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

【讨论】:

  • 谢谢它的工作,,有什么方法可以与visual studio一起使用吗?
  • @venkateshkambakana 我不知道。我只在 Linux 上工作。
【解决方案2】:

如果您可以将要覆盖的函数与将调用它的函数分开,则 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");
}

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

【讨论】:

    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 2021-12-01
    • 2020-05-02
    • 2010-09-24
    • 2021-05-11
    相关资源
    最近更新 更多