【问题标题】:How to pass ellipsis argument to makecontext, which also accepts ellipsis argument in C?如何将省略号参数传递给makecontext,它也接受C中的省略号参数?
【发布时间】:2019-09-10 04:23:29
【问题描述】:

我有一个运行其他函数的函数,这些函数可以有可变数量的参数。

这个函数的参数然后被传递给makecontext,它将函数附加到一个ucontext_t结构,但问题是这个函数也接受可变数量的参数。

所以我的问题是,鉴于我无法更改 makecontext,我如何将从函数获得的省略号参数传递给 makecontext?

void run_function(void (*func), int argc, ...) {
    va_list vl;
    va_start(vl, argc);
    
    makecontext(&ucontext, argc, ...);
    va_end(vl);
}

【问题讨论】:

  • 简短的回答是你不能。这就是为什么 C 中的可变参数函数通常具有采用 va_list 的版本(例如、printf/vprintf)。更长的答案是可能的,但您需要使用libffi 之类的东西。这是评论而不是答案,因为我懒得解释。
  • 另一种可能性是使用可变参数宏而不是 run_function 的函数。对于支持语句表达式的编译器(基本上大多数非 Microsoft 编译器),这可能是非常可行的……
  • 我是这么认为的。只是想澄清一下。谢谢!

标签: c ellipsis ucontext


【解决方案1】:

正如@nemequ 在 cmets 中指出的那样,使用像gcc 这样的编译器,可以使用可变参数宏。但是

  • va_start() 宏需要在可变数量的参数之前至少有一个参数:last 参数是最后一个的名称变量参数列表之前的参数;
  • 传递给makecontext()的函数func()在被调用时传递了可变数量的参数而不是argc参数.

因此,宏包装器强制 argc 作为 func() 的第一个参数,以使其使用 va_start():

#include <ucontext.h>
#include <stdio.h>
#include <stdarg.h>

#define run_function(ucp, func, argc, ...) \
           makecontext(ucp, func, (argc) + 1, argc, ##__VA_ARGS__)

typedef void (* ucfunc_t)(void);

void func1(int argc, ...)
{
  va_list ap;
  int param;
  int i;

  va_start(ap, argc);

  printf("func1() running with %d parameters:\n", argc);
  for (i = 0; i < argc; i ++) {
    param = va_arg(ap, int);
    printf("\t%d\n", param);
  }

  va_end(ap);
}

int main(void)
{
  ucontext_t main_uc, uc1, uc2, uc3;
  char stack1[4096], stack2[4096], stack3[4096];

  getcontext(&uc1);
  uc1.uc_link = &main_uc;
  uc1.uc_stack.ss_sp = stack1;
  uc1.uc_stack.ss_size = sizeof(stack1);

  getcontext(&uc2);
  uc2.uc_link = &uc1;
  uc2.uc_stack.ss_sp = stack2;
  uc2.uc_stack.ss_size = sizeof(stack2);

  getcontext(&uc3);
  uc3.uc_link = &uc2;
  uc3.uc_stack.ss_sp = stack3;
  uc3.uc_stack.ss_size = sizeof(stack3);

  run_function(&uc1, (ucfunc_t)func1, 0);
  run_function(&uc2, (ucfunc_t)func1, 5, 1, 2, 3, 4, 5);
  run_function(&uc3, (ucfunc_t)func1, 2, 1, 2);

  getcontext(&main_uc);
  main_uc.uc_link = NULL;

  swapcontext(&main_uc, &uc3);

  return 0;
}

前面的例子给出了:

$ gcc ex1.c -o ex1
$ ./ex1 
func1() running with 2 parameters:
    1
    2
func1() running with 5 parameters:
    1
    2
    3
    4
    5
func1() running with 0 parameters:

【讨论】:

    猜你喜欢
    • 2020-12-19
    • 2015-01-26
    • 2019-02-01
    • 1970-01-01
    • 2018-06-21
    • 2011-03-09
    • 2013-05-22
    • 2013-06-27
    • 1970-01-01
    相关资源
    最近更新 更多