用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()
测试可能是一个完整的函数,也可能只是测试在函数外部定义的适当范围的变量—文件中的静态变量或外部变量。这避免了使用函数指针;它与现在调用的函数相同。更改函数指针表等同于更改单个变量-它涉及更改存储在函数外部的某些内容的值以更改函数的行为。这是“代码重用”和重构的完美反例。你绝对不应该这样做。这是“代码重用”和重构的完美反例。你绝对不应该这样做。。。。我怎么没有想到这一点。在执行顺序没有争议的情况下,它将不起作用,但如果它不重要,这个解决方案是非常好的。。。。我怎么没有想到这一点。在执行顺序没有争议的情况下,它将不起作用,但如果它不重要,这个解决方案是非常好的。