使用C预处理器生成两个函数

时间:2013-02-02 23:38:49

标签: c c-preprocessor

我有一个项目,并且我有一些经常更改的预处理器#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}})是不可接受的选项。我可以使用复制/粘贴来执行此操作,但这会导致代码重用,从而有可能在一个副本中修复错误而不是另一个副本。

3 个答案:

答案 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()测试可能是一个完整的函数,或者它可能只是测试在函数外部定义的适当范围的变量 - 文件中的静态变量或外部变量。这避免了必须使用函数指针;它与现在称为相同的功能。更改函数指针表相当于更改单个变量 - 它涉及更改存储在函数外部的某些值以更改函数的行为。