visualstudioc链接器包装选项



来自本文用C:中的模拟对象进行单元测试

这是通过使用--wrap链接器选项来完成的,该选项将封装函数的名称作为参数。如果测试是使用gcc编译的,那么调用可能看起来像:

$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c

在visual studio中编译C项目时,如何做到这一点?

ld中的--wrap可以通过MSVC Linker中的/ALTERNATENAME选项进行模拟。

我们从两个编译单元开始,比如从foo.c编译的foo.o,其外部函数在foo.h中声明,以及从main.c中声明main.o。(如果foo被编译成一个库,情况不会有太大变化。)

// foo.h
int foo();
// foo.c
int foo() {
    return 0;
}
// main.c
#include <stdio.h>
#include "foo.h"
int main() {
    int x = foo();
    printf("%sn", x ? "wrapped" : "original");
}

int foo()的返回值为0,因此上面的代码片段将输出"0";"原件";。

现在我们用一个别名覆盖实际实现:main.c中的#include "foo.h"被取代

#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")

让我解释一下这里发生了什么:

  1. #define foo real_foofoo.h中的函数声明修改为int real_foo()
  2. 然而,foo.o中的符号仍然以int foo()命名,而不是以别名int real_foo()命名。这就是为什么我们需要/alternatename链接器开关
  3. "/alternatename:real_foo=foo"告诉链接器,如果找不到名为real_foo的符号,请在抛出错误之前再次尝试foo
  4. 显然int real_foo()没有定义。MSVC链接器将搜索CCD_ 26,并在每次出现CCD_

由于前面的实现已经被别名化,现在我们通过宏将int foo()重定向到我们的新实现:

int wrap_foo() {
    return real_foo() + 1;
}
#define foo wrap_foo

我们在这里结束了。最后main.cpp看起来像:

#include <stdio.h>
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
int wrap_foo() {
    return real_foo() + 1;
}
#define foo wrap_foo
int main() {
    int x = foo();
    printf("%sn", x ? "wrapped" : "original");
}

内置在MSVC中;"包裹";。

相关内容

  • 没有找到相关文章

最新更新