pog*_*man 8 c linker visual-studio cmocka
从这篇文章中使用 C 中的模拟对象进行单元测试:
这是通过使用
--wrap链接器选项来完成的,该选项将包装函数的名称作为参数。如果测试是使用 gcc 编译的,则调用可能如下所示:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
在 Visual Studio 中编译 C 项目时如何做到这一点?
小智 5
可以通过MSVC --wrapLinker中的选项来模拟。ld/ALTERNATENAME
我们从两个编译单元开始,例如foo.o从 编译,其外部函数在和中foo.c声明。(如果已经编译为库,事情不会有太大变化。)foo.hmain.omain.cfoo
// foo.h
int foo();
// foo.c
int foo() {
return 0;
}
// main.c
#include <stdio.h>
#include "foo.h"
int main() {
int x = foo();
printf("%s\n", x ? "wrapped" : "original");
}
Run Code Online (Sandbox Code Playgroud)
返回值int foo()是0,所以上面的代码片段将输出“original”。
现在我们用别名覆盖实际的实现:#include "foo.h"inmain.c被替换为
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
Run Code Online (Sandbox Code Playgroud)
让我解释一下这里发生了什么:
#define foo real_foo, 中的函数声明foo.h被修改为int real_foo()。foo.o仍然以 命名int foo(),而不是别名int real_foo()。这就是我们需要/alternatename链接器开关的原因。"/alternatename:real_foo=foo"告诉链接器,如果找不到名为 的符号real_foo,请foo在抛出错误之前重试。int real_foo()。int foo()MSVC 链接器将在每次出现 时搜索并链接它int real_foo()。由于之前的实现已被别名,现在我们int foo()通过宏重定向到新的实现:
int wrap_foo() {
return real_foo() + 1;
}
#define foo wrap_foo
Run Code Online (Sandbox Code Playgroud)
我们到这里就完成了。最后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("%s\n", x ? "wrapped" : "original");
}
Run Code Online (Sandbox Code Playgroud)
内置MSVC,它将输出“wrapped”。
| 归档时间: |
|
| 查看次数: |
1416 次 |
| 最近记录: |