我正在修改其他人编写的代码。
现有代码包含算法,适用于两种情况。差异很小 - 一些数据类型,有时还有一些额外的行处理。
原始代码将所有内容设置为
#define ABC
#ifdef ABC
typedef struct {
unsigned char a, b, c;
} MyStruct;
#else
typedef unsigned char MyStruct;
#endif
#if defined(ABC)
#define SIZE1 3
#else
#define SIZE1 2
#endif
typedef struct {
MyStructtable[SIZE1];
} MyStructA;
void MyMethod(){
statement1;
#if defined(ABC)
staement2;
#endif
}
它的工作原理......如果在源代码中做出选择,但是我试图让用户选择使用一个版本或另一个版本,并且最难分开代码。
我可以为每个版本创建一套完整的文件。我遇到的问题:
由于存在复杂的算法,因此将算法保存在一个位置是有意义的...如果在一个版本而不是其他版本中进行更改,则复制代码可能会导致错误。
我试图做一些类型
if(option)
{
#define ABC
}
else
{
#undef ABC
}
但是调试器会跳过并且看不到定义的ABC,即使是在过了"是"分支。
有没有办法解开这段代码,还是我必须创建清晰的单独路径 - 复制整个代码?
答案 0 :(得分:1)
之前我做过类似的事情。我有一个我没有源代码的库,但我确实有一个标题。有很多代码使用这个库,也比我自己改变的方式更多。
我必须编写另一个库来编写与另一个库相同的东西,但是使用不同的设备,驱动程序等。你得到了图片。所以在运行时我想用我的库代替它们,但仍然能够使用旧的(必须向后兼容)。
所以我做的是:我提出了一些方便的宏,可以将文本转换为其他定义。有2个头文件和一个源文件。例如,假设我想在运行时将FooLibrary替换为可选择的BarLibrary。在一个名为FooLibrary.h的头文件中:
// don't ask me why, but two levels of indirection is necessary
// to pull off a certain concatenation
// this I got from another question on SO
#define CAT(x, y) x ## y
#define cat(x, y) CAT(x, y)
#ifdef FOO_HIJACK_NAMESPACE
// library init functions
bool ShouldHijack();
void SetHijack(bool yn);
// handy-dandy function-changing macros
#define FOO_FN_NAME(X) cat(X, FOO_HIJACK_NAMESPACE)
#define FOO_FN_NAME_NS(X) FOO_HIJACK_NAMESPACE :: FOO_FN_NAME(X)
#define FOO_DECL(X) FOO_API FOO_FN_NAME(X)
#define FOO_IMPL(X) FOO_API FOO_FN_NAME_NS(X)
#define FOO_CALL(X) (ShouldHijack() ? FOO_FN_NAME_NS(X) : X)
namespace FOO_HIJACK_NAMESPACE {
#else
#define FOO_DECL(X) X
#define FOO_IMPL(X) X
#define FOO_CALL(X) X
#endif // FOO_HIJACK_NAMESPACE
然后,在这个命名空间包装器中你重新定义函数调用,如下所示:在你的另一个库中有一个函数bool BarFun(fooargs...)
,你可以将它重新定义为
bool FOO_DECL(BarFun)(fooargs...);
// more FOO_DECL's...
在FooLibrary.h中。 FOO_API
是您常用的cdecl
类垃圾,对我来说,我正在做#define FOO_API WINAPI
。添加类似的声明直到最后,不要忘记关闭命名空间:
#ifdef FOO_HIJACK_NAMESPACE
}
#endif // FOO_HIJACK_NAMESPACE
然后,在FooLibrary.cpp中,您提供了类似的实现:
#include "FooLibrary.h"
// hijack
static bool bShouldHijack = false;
bool ShouldHijack() { return bShouldHijack; }
void SetHijack(bool yn) { bShouldHijack = yn; }
bool FOO_IMPL(BarFun)(fooargs...)
{
// your implementation here...
}
// more FOO_IMPL's...
等等。最后,你再制作一个我想调用的头文件" FooLibraryHijacked.h":
#include "FooLibrary.h"
#define BarFun FOO_CALL(BarFun)
// more #define's...
为每个函数提供一个重新声明,一个重新实现和一个#define
。我有20个这样的函数,所以我使用正则表达式为我生成它们。
最后,要在目标代码文件中使用它,#include "FooLibraryHijacked.h"
作为上一个#include
,或者至少在#include "BarLibrary.h"
之后。然后#define
宏FOO_HIJACK_NAMESPACE
作为内容,在预处理器获得它之后,说" Foo"和BarFun
变为Foo::BarFunFoo
。
现在如何使用单独的类型定义来实现它将会很有趣。如果应用程序代码只将变量从一个函数传递到另一个函数,也许你可以使用不透明指针。