简体   繁体   中英

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

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);
}

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM