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: