【问题标题】:C - dynamic function callC - 动态函数调用
【发布时间】:2014-03-27 23:30:40
【问题描述】:

我有一个测试文件,其中测试定义为

static int test1(){
    /*some tests here*/
    return 0;
}
static int test2(){
    /*some tests here*/
    return 0;
}
/*...etc*/`

我想知道是否有一种方法可以循环调用所有测试,而不是为每个测试编写调用。 (有一些函数我需要在每次测试之前和之后调用,并且有超过 20 次测试,这可能会变得非常烦人。我也一直对做这样的事情感到好奇。)

我在想类似的事情:

int main(){
    int (*test)() = NULL;
    for(i = 1; i <= numtests; i++){
      /*stuff before test*/
      (*test)();
      /*stuff after test*/
    }
    return 0;
}

但我不确定如何继续使用“i”的值来设置测试指针。

【问题讨论】:

  • 你在哪个平台上?从技术上讲,在 *NIX 平台上,你应该可以使用dlsym 和朋友来动态调用函数,虽然我并不推荐它。
  • 我通过 ssh 连接到我学校的 linux 服务器。我不知道 dlsym 是做什么的,我现在不想让自己感到困惑,但我稍后会查一下。下面发布了一个工作(且看起来很有趣)的解决方案,但感谢您的回复:)

标签: c dynamic-function


【解决方案1】:

您可以使用自包含技巧来获取函数指针列表:

#ifndef LIST_TESTS
#define TEST(name, ...) static int name() __VA_ARGS__

/* all includes go here */
#endif // ifndef LIST_TESTS

TEST(test1, {
  /* some tests here */
  return 0;
})

TEST(test2, {
  /* some tests here */
  return 0;
})

#undef TEST

#ifndef LIST_TESTS
int main(void) {
  int (*tests[])() = {
    #define LIST_TESTS
    #define TEST(name, ...) name,
    #include __FILE__
  };
  int num_tests = sizeof(tests) / sizeof(tests[0]);
  int i;

  for (i = 0; i < num_tests; ++i) {
    /* stuff before test */
    (tests[i])();
    /* stuff after test */
  }

  return 0;
}
#endif // ifndef LIST_TESTS

【讨论】:

  • 谢谢,这是一个很棒的解决方案!您能解释一下“VA_ARGS”部分的工作原理吗?它只是抓取“...”的参数槽中的任何内容吗?
  • @SaintlyWolf __VA_ARGS__ 被在... 位置提供给宏的任何参数所取代。如果没有该构造,您将无法在测试正文中使用逗号。 LIST_TESTSmain 中定义。
  • 非常感谢您对此提供的帮助。这是我想了很久的事情。可悲的是,我的教授为此类所需的编译器选项阻止了可变参数宏。不过,在我完成这门课后,我一定会记住这一点!
【解决方案2】:

在 Linux 上

将函数放在单独的共享库 (.so) 中。然后用dlopen打开它,用dlsym通过它的名字得到一个函数指针

在窗户上

将函数放在一个单独的 dll 中(基本上是一样的)。然后用 LoadLibrary 打开它,用 GetProcAddress 获取指向函数的指针

更多你想做的打字,但它会让你做你想做的事

【讨论】:

  • 虽然这可能有效,但它实际上并没有用于此目的,因为它根本没有简化流程。
【解决方案3】:

你可以做的是用你的所有函数定义一个函数指针数组,然后在数组的所有元素中循环。

int (*array[])(void) = {test1, test2, test3};

【讨论】:

  • 感谢您的回答。我已经想到了,但希望有一种根本不涉及键入函数名称的方法。不是说我介意输入它们,我只是希望能够做到,如果语言允许的话。
  • @SaintlyWolf 我想不出更好的解决方案。
  • @SaintlyWolf 你必须在某个时候引用实际的函数。
猜你喜欢
  • 1970-01-01
  • 2020-06-28
  • 1970-01-01
  • 2013-02-28
  • 2014-12-21
  • 2012-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多