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

用C预处理器生成两个函数,c,c-preprocessor,C,C Preprocessor,我有一个项目和一个案例,其中我有一些经常更改的预处理器#define来控制它的工作方式--例如: 这很好,尽管每次都必须重新编译,所以它位于“每次都必须重新编译的内容”文件中。我想把它推到一个[静态]库中。我可以更改它的调用方式(已经有一个函数指针用于选择myFunction),所以我希望它变成 void myfunction(int num, mystruct* content) { doSomethingTo(content); //... } void myfunction

我有一个项目和一个案例,其中我有一些经常更改的预处理器
#define
来控制它的工作方式--例如:

这很好,尽管每次都必须重新编译,所以它位于“每次都必须重新编译的内容”文件中。我想把它推到一个[静态]库中。我可以更改它的调用方式(已经有一个函数指针用于选择
myFunction
),所以我希望它变成

void myfunction(int num, mystruct* content) {
    doSomethingTo(content);
    //...
}
void myfunction_featureX(int num, mystruct* content) {
    doSomethingTo(content);
    //...
    feature_x(content);
}

我需要在几个地方执行此操作,因此为每个库使用单独的库(一个带
-D FEATURE_X,一个不带
-D FEATURE_X
)是不可接受的选择。我可以通过复制/粘贴来实现这一点,但这会导致代码重用,这会带来修复一个副本中的错误而不是另一个副本中的错误的风险。

让featureX版本的函数调用主线函数。在您的示例中,
myfunction\u featureX
将调用
myfunction
,然后执行自己的操作。

让featureX版本的函数调用主线函数。在您的示例中,
myfunction\u featureX
将调用
myfunction
,然后执行自己的操作。

如果您将myfeature\u 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;
}
然后,如果不使用该功能,则只需使用
NULL
s填充虚拟函数表,如果要使用,则使用函数指针填充虚拟函数表。您可以在任何地方执行此操作-例如,您的静态库。。或者,您可以将
功能_x
编译到动态库中,在运行时加载它,如果加载成功,则填充函数表,并在卸载动态链接库时清除该表


我认为与Jonathan Leffler的方法相比,它真正给您带来的唯一好处是,feature_x的代码实际上不需要与其他代码链接到同一个二进制文件中。如果您所需要的只是一个运行时开关来打开或关闭该功能,那么一个简单的
If
语句应该可以实现这一点,正如Jonathan Leffler所建议的那样。(顺便说一句,这里也有一个
if
-它检查函数表的内容:)

如果您将myfeature\u 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;
}
然后,如果不使用该功能,则只需使用
NULL
s填充虚拟函数表,如果要使用,则使用函数指针填充虚拟函数表。您可以在任何地方执行此操作-例如,您的静态库。。或者,您可以将
功能_x
编译到动态库中,在运行时加载它,如果加载成功,则填充函数表,并在卸载动态链接库时清除该表


我认为与Jonathan Leffler的方法相比,它真正给您带来的唯一好处是,feature_x的代码实际上不需要与其他代码链接到同一个二进制文件中。如果您所需要的只是一个运行时开关来打开或关闭该功能,那么一个简单的
If
语句应该可以实现这一点,正如Jonathan Leffler所建议的那样。(顺便说一句,这里也有一个
if
-它检查函数表的内容:)

当然,这就是将功能X的激活从编译时问题更改为运行时问题的点:

void myfunction(int num, mystruct* content)
{
    doSomethingTo(content);
    //...
    if (FeatureX_Enabled())
        feature_x(content);
}

FeatureX\u Enabled()
测试可能是一个完整的函数,也可能只是测试在函数外部定义的适当范围的变量—文件中的静态变量或外部变量。这避免了使用函数指针;它与现在调用的函数相同。更改函数指针表等同于更改单个变量-它涉及更改存储在函数外部的某些内容的值以更改函数的行为。

当然,这就是将功能X的激活从编译时问题更改为运行时问题的点:

void myfunction(int num, mystruct* content)
{
    doSomethingTo(content);
    //...
    if (FeatureX_Enabled())
        feature_x(content);
}

FeatureX\u Enabled()
测试可能是一个完整的函数,也可能只是测试在函数外部定义的适当范围的变量—文件中的静态变量或外部变量。这避免了使用函数指针;它与现在调用的函数相同。更改函数指针表等同于更改单个变量-它涉及更改存储在函数外部的某些内容的值以更改函数的行为。

这是“代码重用”和重构的完美反例。你绝对不应该这样做。这是“代码重用”和重构的完美反例。你绝对不应该这样做。。。。我怎么没有想到这一点。在执行顺序没有争议的情况下,它将不起作用,但如果它不重要,这个解决方案是非常好的。。。。我怎么没有想到这一点。在执行顺序没有争议的情况下,它将不起作用,但如果它不重要,这个解决方案是非常好的。