我有一个项目,并且我有一些经常更改的预处理器#define
来控制它的工作原理 - 例如:
void myfunction(int num, mystruct* content) {
doSomethingTo(content);
//...
#ifdef FEATURE_X
feature_x(content);
#endif
}
这样可以正常工作,虽然它每次都必须重新编译,因此它位于“每次必须重新编译的文件”中。我想将它推入[静态]库中。我可以改变它的调用方式(已经有一个用于选择myFunction
的函数指针),所以我希望它变成
void myfunction(int num, mystruct* content) {
doSomethingTo(content);
//...
}
void myfunction_featureX(int num, mystruct* content) {
doSomethingTo(content);
//...
feature_x(content);
}
我需要在几个地方执行此操作,因此对于每个库使用单独的库(一个带有-D FEATURE_X
和一个没有{{1}})是不可接受的选项。我可以使用复制/粘贴来执行此操作,但这会导致代码重用,从而有可能在一个副本中修复错误而不是另一个副本。
答案 0 :(得分:1)
让featureX版本的函数调用主线函数。在您的示例中,myfunction_featureX
会调用myfunction
,然后执行自己的操作。
答案 1 :(得分:1)
如果将myfeature_x放在函数表中会有帮助吗?
#include <stdio.h>
#include <string.h>
typedef struct {
int x,y;
} mystruct;
typedef void (*fn_ptr)(mystruct* content);
fn_ptr vtable[10];
#define FEATURE_X_INDEX 0
void feature_x(mystruct *content)
{
printf("y: %d\n", content->y);
}
void myfunction(int num, mystruct* content) {
printf("x: %d\n", content->x);
//...
if (vtable[FEATURE_X_INDEX]) {
vtable[FEATURE_X_INDEX](content);
}
}
int main(void)
{
bzero(vtable, sizeof(vtable));
mystruct s;
s.x = 1;
s.y = 2;
myfunction(0, &s);
if (1) {
//Of course you'd use a more sensible condition.
vtable[FEATURE_X_INDEX] = feature_x;
}
myfunction(0, &s);
return 0;
}
输出:
x: 1
x: 1
y: 2
然后,您需要做的就是使用NULL
填充虚拟函数表(如果不使用该函数),并使用函数指针(如果要使用它)。这可以从你想要的任何地方做 - 例如你的静态库..或者你可以将feature_x
编译成动态库,在运行时加载它,如果加载成功则填充函数表,并清除表时动态链接库已卸载。
我认为这对Jonathan Leffler方法的唯一好处是,feature_x的代码实际上并不需要与其他代码链接到相同的二进制文件中。如果您只需要一个运行时开关来打开或关闭该功能,那么简单的if
语句应该可以解决问题,正如Jonathan Leffler建议的那样。 (顺便提一下,这里也有一个if
- 它检查功能表的内容:))
答案 2 :(得分:1)
当然,您可以将功能X的激活从编译时问题更改为运行时问题:
void myfunction(int num, mystruct* content)
{
doSomethingTo(content);
//...
if (FeatureX_Enabled())
feature_x(content);
}
FeatureX_Enabled()
测试可能是一个完整的函数,或者它可能只是测试在函数外部定义的适当范围的变量 - 文件中的静态变量或外部变量。这避免了必须使用函数指针;它与现在称为相同的功能。更改函数指针表相当于更改单个变量 - 它涉及更改存储在函数外部的某些值以更改函数的行为。