我喜欢GNU链接器功能来包装很多函数.我通常使用它来模拟例如rand()之类的非确定性函数调用.考虑以下示例,我想为giveMeanumber编写单元测试:
//number.cpp
int giveMeANumber() {
return rand() % 6 + 1;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用GNU链接器功能包装来调用rand,如下所示:
//test.cpp
extern "C" int __wrap_rand(void) {
return 4;
}
void unitTest() {
assert giveMeANumber() == 5;
}
$ g++ test.cpp -o test number.o -Xlinker --wrap=rand
Run Code Online (Sandbox Code Playgroud)
有没有办法对普通的C++函数做同样的事情?以下不起作用,我想这是因为名称错误.但即使我用错误的名字尝试它也不起作用.
//number.cpp
int foo() {
//some complex calculations I would like to mock
}
int giveMeANumber() {
return foo() % 6 + 1;
}
//test.cpp
extern "C" int __wrap_foo(void) {
return 4;
}
$ g++ test.cpp -o test number.o -Xlinker --wrap=foo
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我尝试在GNU的链接器包装选项的帮助下包装模板函数.代码如下所示:
// f.h
template<typename T>
void f(T t) {
}
// bar.h
void bar();
// bar.cpp
#include "bar.h"
#include "f.h"
void bar() {
f(42);
}
// test.cpp
extern "C" {
extern void __real__Z1fIiEvT_(int i);
void __wrap__Z1fIiEvT_(int i) {
__real__Z1fIiEvT_(i);
}
}
int main() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
上面显示的代码与以下命令链接:
g++ -Xlinker -wrap=_Z1fIiEvT_ -o test test.o bar.o
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用,并且始终调用原始函数f而不是我的包装版本__wrap__Z1fIiEvT_.你看到我犯过什么错误吗?
编辑:建议,我在这里附加nm的输出,以确保我没有使用模板函数的错位名称做任何错误:
$ g++ -c bar.cpp -o bar.o
$ nm bar.o
0000000000000000 W _Z1fIiEvT_
Run Code Online (Sandbox Code Playgroud) 如果我在目标文件和库中定义了相同的符号,GNU链接器将从目标文件中获取符号.考虑这个例子:
g++ -L"dir/to/lib" -o Executable Test.o foo.o -lMyLib
Run Code Online (Sandbox Code Playgroud)
如果我foo在foo.cpp中定义了一个具有相同签名的函数,并且在源文件中编译了"MyLib",那么如果我使用这个顺序,GNU链接器总是更喜欢前一个.
这种行为GNU工具链是否具体?您是否知道其他链接器的行为方式相同?这是否记录在案(GNU文档,C++标准)?我找不到任何东西......
我想在进行单元测试(也就是链接接缝)时使用此功能来替换/模拟某些功能.