在静态库中重写C函数
Overiding C functions in static library
我得到多个定义错误,不明白为什么。
我在Cygwin上用g++编译C代码。我正在使用单元测试框架(谷歌测试,这是c++,这就是为什么我不使用gcc)。单元测试源文件#包含包含我想要进行单元测试的函数的.c文件(fileA.c),实质上使其成为该文件的扩展,然后编译单元测试源文件。被测试的函数调用在fileB.h中声明并在fileB.c中定义的函数。这有点像c中的重写函数调用,我没有展示包含保护,但本质上剥离后的代码看起来像这样:
fileB.h
typedef void * pClass; // to hide the "class" in the .c file
extern pClass pObject1;
void do_something_with_object( void * );
fileB.c
#include "FileB.h"
typedef struct myclass {
int stuff;
} myclass;
myclass Obj1 = { initial_value };
void *pObj1 = &Obj1;
void do_something_with_object( void *arg) {
// do stuff, casting to myclass and verifying it's the right kind
}
fileA.h
#include "fileB.h"
void myfunc( void );
fileA.c
#include "fileA.h"
void myfunc( void ) {
do_something_with_object( pObj1 );
}
utest_fileA.cpp
#include "../fileA.c"
// google test infrastructure stuff not shown
TEST(testname, testcase) {
myfunc();
}
fileB的符号被链接到一个包含所有生产代码的静态库中。静态库是用g++编译的,所以没有extern "C"
问题。utest_fileA.cpp的makefile静态链接在这个库中。到目前为止一切顺利。现在,我想提供我自己的do_something_with_object的伪版本,这样我就可以监视传入的内容,以确保myfunc使用正确的参数调用do_something_with_object。我不想仅仅为了支持这个单元测试而修改生产代码。因此,我在单元测试源的编译单元中进一步创建了do_something_with_object的假版本:
static void * myspy;
void do_something_with_object( void * arg) {
myspy = arg;
}
的想法是,单元测试将使用假的定义,因为它有一个定义,它不会费心在静态库中寻找它,并且不会有冲突。这通常是有效的。但在我现在遇到的情况下,我得到do_something_with_object()的多个定义错误,首先找到假的,然后才是真正的。我看不出这与实际情况有什么不同,但显然我遗漏了什么。是什么原因造成的呢?我应该注意什么?尝试链接utest_fileA时失败。使用libmylib。它使用-static标志。我尝试了一些我在stackoverflow的其他地方看到的建议,比如-z muldefs,但是Cygwin不喜欢这样,我真的很想了解发生了什么。
多个定义的原因是fileB.h中的"extern pClass Object1"。作为一个未解析的外部对象,当对象文件包含它时,链接器会将定义它的对象拉入,即fileB.o。链接器拉入整个文件b。而不仅仅是一个符号,所以函数定义也被拉了进来。因此,当单元测试代码编译并具有spy定义时,它编译得很好。但是当链接器试图在静态库中链接时,它会发现另一个定义,链接失败。
没有尝试通过让链接器首先找到spy版本来覆盖静态库中的函数调用,我最终给了spy一个稍微不同的名称,并使用预处理器将其交换到单元测试中。这允许产品代码保持不变。它与C中Override a function call中选择的答案类似,但不完全相同,因为spy及其预处理器指令是在一个单独的文件中定义的,该文件可以包含在任何单元测试中,因此不需要在特定的头文件中注册替换。
- 在 C++ 中用派生类型重写成员函数
- 重写虚拟函数和继承
- C++调用使用重写函数的父类函数
- 重写打印函数而不是覆盖基类
- 重写函数不打印基类数据
- 将一个小的 C 定义重写为"normal" C++函数
- 重写另一个方法 [C++] 使用的超类回调函数
- 具有派生参数的函数重写
- 在回调中使用函数时,C++未知重写说明符
- 用模板化函数重写虚拟函数
- 没有函数重写的多重继承.为什么模棱两可
- C++ 继承构造函数重写
- 关于C++中的虚拟函数重写
- C++函数重写不起作用
- 如何实现类变量的虚拟函数重写
- 将C++函数重写为C#(将指针传递到数组中的下一个元素)
- 引用可以用于实现函数重写吗
- 用函数重写嵌套的if-else语句
- C++继承函数重写
- 本机C++中的函数重写