How to pass ellipsis argument to makecontext, which also accepts ellipsis argument in C?

喜你入骨 提交于 2021-01-29 09:32:06

问题


I have a function that runs other functions, and these functions can have a variable number of arguments.

The parameter of this function is then passed to makecontext, which attaches the function to a ucontext_t structure, but the problem is this function also takes variable number of arguments.

So my question is, how do I pass ellipsis argument obtained from a function to makecontext given that I can't change makecontext?

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

回答1:


As pointed out in the comments by @nemequ, with a compiler like gcc, it is possible to use a variadic macro. But

  • The va_start() macro needs at least one parameter before the variable number of parameters: the last parameter is the name of the last argument before the variable argument list;
  • The function func() passed to makecontext() is passed the variable number of parameters but not the argc parameter when it is called.

Hence, the macro wrapper forces argc as first parameter for func() to make it use 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;
}

The previous example gives:

$ 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:


来源:https://stackoverflow.com/questions/55769608/how-to-pass-ellipsis-argument-to-makecontext-which-also-accepts-ellipsis-argume

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!