When using the function, makecontext
, from <ucontext_t.h>
in C, it takes the arguments (ucontext_t* context, void (*someFunction)(void), int numberOfArguments, ...)
. The numberOfArguments
is to pass in arguments into someFunction
, but when passing in arguments, I get compile warnings.
I need to, or should, remove these since this is for a school project and warnings may make me lose points. I think I'm allowed to edit the flags of the Makefile, but I'd prefer to adjust the code.
I did 2 tests.
1: Passed a function and string as arguments
The code for test1 is:
#include <stdio.h>
#include <ucontext.h>
// Outputs arg as a string
void* f(void* arg) {
printf("%s\n", (char*)arg);
return 0; // Returns back to c0
}
// makecontext takes as argument2, (void (*)(void)), but allows (void (*)(...))
// I want to remove the warning from using (void (*)(...))
void helper(void* (*selectFunction)(void*), void* selectArg) {
// Calls select function with select argument
selectFunction(selectArg);
}
int main()
{
// Initialize contexts
ucontext_t c0, c1;
char stack[1024];
getcontext(&c1);
// Setup stack for c1
c1.uc_stack.ss_sp = stack;
c1.uc_stack.ss_size = sizeof(stack);
c1.uc_link = &c0; // Swap to c0 stack on c1 stack end
void* (*selectFunction)(void*) = &f;
void* selectArg = (void*)("abc123 testing testing");
// Passes function f with arg "abc123 testing testing" to helper
makecontext(&c1, helper, 2, selectFunction, selectArg);
// Swap to context that calls function helper
swapcontext(&c0, &c1);
printf("Welcome back\n");
return 0;
}
My output for test1 is:
$gcc -o main *.c
main.c: In function ‘main’:
main.c:33:22: warning: passing argument 2 of ‘makecontext’ from incompatible pointer type [-Wincompatible-pointer-types]
makecontext(&c1, helper, 2, selectFunction, selectArg);
^~~~~~
In file included from main.c:2:0:
/usr/include/ucontext.h:47:13: note: expected ‘void (*)(void)’ but argument is of type ‘void (*)(void * (*)(void *), void *)’
extern void makecontext (ucontext_t *__ucp, void (*__func) (void),
^~~~~~~~~~~
$main
abc123 testing testing
Welcome back
2: Passed an int as argument
The code for test2 is:
#include <stdio.h>
#include <ucontext.h>
// Outputs arg as a string
void f(int n) {
printf("%d\n", n);
return; // Returns back to c0
}
// makecontext takes as argument2, (void (*)(void)), but allows (void (*)(...))
// I want to remove the warning from using (void (*)(...))
void helper(int arg) {
// Calls f with arg
f(arg);
}
int main()
{
// Initialize contexts
ucontext_t c0, c1;
char stack[1024];
getcontext(&c1);
// Setup stack for c1
c1.uc_stack.ss_sp = stack;
c1.uc_stack.ss_size = sizeof(stack);
c1.uc_link = &c0; // Swap to c0 stack on c1 stack end
// Make a context to run f with argument 5
makecontext(&c1, helper, 1, 5);
// Swap to context that calls function helper
swapcontext(&c0, &c1);
printf("Welcome back\n");
return 0;
}
My output for test2 is:
$gcc -o main *.c
main.c: In function ‘main’:
main.c:30:22: warning: passing argument 2 of ‘makecontext’ from incompatible pointer type [-Wincompatible-pointer-types]
makecontext(&c1, helper, 1, 5);
^~~~~~
In file included from main.c:2:0:
/usr/include/ucontext.h:47:13: note: expected ‘void (*)(void)’ but argument is of type ‘void (*)(int)’
extern void makecontext (ucontext_t *__ucp, void (*__func) (void),
^~~~~~~~~~~
$main
5
Welcome back
The parameter someFunction
is of type void(*)(void)
, which requires to be passed a pointer to a function that takes no arguments and returns void
(not void *
)
You can arrange for it to work, changing the definition of someFunction
into something like:
void *(*someFunction)() /* don't specify the argument list */
Int this case, the compiler will accept any function that returns void *
, but then you have to double check that the function you pass has the proper number and types of arguments. This is called an incomplete type definition, and it is very error prone (it is conserved from ancient C, long time before the ANSI revision)
if you want a function that takes a void *
argument and returns a void *
result, change the definition of someFunction
to:
void *(*someFunction)(void *), ...
But if this is an academic exercise, I suggest you to do full type checking, and don't try to use the C facilities to make mistakes :) (they require you know very well what you are doing)
In your case, the helper function requires an int
parameter, which is not a void *
(indeed, most probably they are not even the same size) so the body of the makecontext
function will not be able to call it correctly. The compiler is there to protect you from yourself.