编译时的C函数装饰器(包装器)

时间:2009-07-24 15:46:52

标签: c wrapper decorator c-preprocessor

我试图在预处理器的帮助下改变 C 中某些函数的行为;并添加可以打开或关闭的可选参数...

可选参数的基本模式很简单:

#ifdef OPT_PARAM
  #define my_func(a, b, opt) _my_func(a, b, opt)
#else
  #define my_func(a, b, opt) _my_func(a, b)
#endif

/*the rest of the code always calls "my_func" with all the params
and not the underscored version...*/

#ifdef OPT_PARAM
void _my_func(int a, int b, int opt)
#else
void _my_func(int a, int b)
#endif
{
  /*... more #ifdefs surrounding opt uses */
}

有条件地包装函数的模式是类似的,但问题是下划线开始加起来(每个嵌套级别一个额外的,可以是一个不同的函数,或者只是一个#define用于下一级别的情况它没有被包裹。)

那么,有关如何降低代码复杂性的任何想法吗?

P.S。我愿意使用Python ......但这是给一个驱动程序: - (

4 个答案:

答案 0 :(得分:2)

好像你想使用默认参数或C中没有的东西。这似乎是一个坏主意。为什么不以更C方式处理事物,如果你不想指定参数,你只需传递NULL或-1(标准)。

void function (int a, int b, int c) {
  if (c != -1) {
    // something
  }
}

function(a,b,-1);
function(a,b,c);

答案 1 :(得分:2)

您可以使用C ++编译器吗?你可以使用(C ++特性)函数重载。

另一种选择是

#ifdef OPT_PARAM
#  define OPT(X) , X
#else
#  define OPT(X)  
#endif

int my_func(int a, int b OPT(int opt) ) {
#ifndef OPT_PARAM
  int opt = default_value;
#endif
  ... // Rest of code
}  


...
// calling it
my_func(2, 4 OPT( 42 ) );

答案 2 :(得分:1)

我认为这可能更接近你想要的,但我不确定。我的理解是允许c函数具有任意数量的参数,这些参数经过类型检查并且可以在编译时消除。

让我通过引用标准来警告您在标识符中使用下划线。您可能会遇到保留的标识符。但是,我不知道这种可能性。

ISO / IEC 9899:1999(E)7.1.3

  

- 所有以。开头的标识符   下划线和大写   信或其他下划线   总是保留用于任何用途。

此解决方案需要GCC。 GCC版本还必须支持弱符号。我们的想法是允许编译器使用弱符号查找正确的函数定义。此外,通过使用编译器应该修剪死分支的知识来简化函数的内容,即:

if (0) { ... }

在编译时没有进一步分析(GCC 4.x肯定会这样做)。通过将不存在的可选参数定义为c预处理器(cpp)符号,可以避免在函数体中具有cpp条件(如果需要)。了解如何为下面的f_opt0定义opt1和opt2。

#include <assert.h>
#include <stdio.h>

extern void f_opt0(int a, int b) __attribute__((weak));
extern void f_opt1(int a, int b, int opt1) __attribute__((weak));
extern void f_opt2(int a, int b, int opt1, int opt2) __attribute__((weak));

#ifdef OPT0
void f_opt0(int a, int b) {
#define opt1 0
#define opt2 0
#endif
#ifdef OPT1
void f_opt1(int a, int b, int opt1) {
#define opt2 0
#endif
#ifdef OPT2
void f_opt2(int a, int b, int opt1, int opt2) {
#endif
  if (opt1) printf("opt1=%d\n", opt1);
  if (opt2) printf("opt2=%d\n", opt2);
  printf("a+b=%d\n", a+b);
  #undef opt1
  #undef opt2
}

#define f(a, b, o1, o2) \
  if (f_opt2) f_opt2(a, b, o1, o2); \
  else if (f_opt1) f_opt1(a, b, o1); \
  else if (f_opt0) f_opt0(a, b); \
  else { assert(0 && "no f() defined!"); }

int main(void) {
  f(1, 2, 1, 1);
  return 0;
}

我的测试非常有限,我并不认为这是C中的优秀设计。它似乎容易出现问题而且很难理解。但是,我希望它能解决你的目标。

答案 3 :(得分:0)

最后我添加了一个新的装饰器,它统一处理了额外的参数,并用更具描述性的名称改变了模糊的下划线。

现在它是一个更正交的设计,我可以在编译时插入和拔出行为,而不会产生运行时开销。

相关问题