visual studio c 链接器包装选项?
visual studio c linker wrap option?
来自这篇文章Unit testing with mock objects in C:
This is done by using the --wrap
linker option which takes the name of the wrapped function as an argument. If the test was compiled using gcc, the invocation might look like:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
在 visual studio 中编译 C 项目时如何执行此操作?
ld
中的 --wrap
可以通过 MSVC 链接器中的 /ALTERNATENAME
选项模拟。
我们从两个编译单元开始,比如说foo.o
编译自foo.c
,其外部函数在foo.h
中声明,main.o
来自main.c
.
(如果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("%s\n", x ? "wrapped" : "original");
}
int foo()
的return值为0,所以上面的代码片段会输出“original”。
现在我们用别名覆盖实际的实现:main.c
中的 #include "foo.h"
被替换为
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
让我解释一下这里发生了什么:
- 被
#define foo real_foo
,foo.h
中的函数声明修改为int real_foo()
.
- 但是,
foo.o
中的符号仍然以 int foo()
命名,而不是别名 int real_foo()
。这就是为什么我们需要 /alternatename
linker 开关。
"/alternatename:real_foo=foo"
告诉 linker,如果找不到名为 real_foo
的符号,请在抛出错误之前再次尝试 foo
。
- 显然没有
int real_foo()
的定义。 MSVC 链接器将在每次出现 int real_foo()
. 时搜索 int foo()
和 link
由于之前的实现已经被别名化,现在我们通过宏将 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("%s\n", x ? "wrapped" : "original");
}
内置于 MSVC 中,它将输出“wrapped”。
来自这篇文章Unit testing with mock objects in C:
This is done by using the
--wrap
linker option which takes the name of the wrapped function as an argument. If the test was compiled using gcc, the invocation might look like:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
在 visual studio 中编译 C 项目时如何执行此操作?
ld
中的 --wrap
可以通过 MSVC 链接器中的 /ALTERNATENAME
选项模拟。
我们从两个编译单元开始,比如说foo.o
编译自foo.c
,其外部函数在foo.h
中声明,main.o
来自main.c
.
(如果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("%s\n", x ? "wrapped" : "original");
}
int foo()
的return值为0,所以上面的代码片段会输出“original”。
现在我们用别名覆盖实际的实现:main.c
中的 #include "foo.h"
被替换为
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
让我解释一下这里发生了什么:
- 被
#define foo real_foo
,foo.h
中的函数声明修改为int real_foo()
. - 但是,
foo.o
中的符号仍然以int foo()
命名,而不是别名int real_foo()
。这就是为什么我们需要/alternatename
linker 开关。 "/alternatename:real_foo=foo"
告诉 linker,如果找不到名为real_foo
的符号,请在抛出错误之前再次尝试foo
。- 显然没有
int real_foo()
的定义。 MSVC 链接器将在每次出现int real_foo()
. 时搜索
int foo()
和 link
由于之前的实现已经被别名化,现在我们通过宏将 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("%s\n", x ? "wrapped" : "original");
}
内置于 MSVC 中,它将输出“wrapped”。