Dynamic conversion of parameters to variable functions

I was wondering if there is a way to dynamically pass parameters to variational functions. those. if i have a function

int some_function (int a, int b, ...){/*blah*/} 

and I accept a bunch of values ​​from the user, I want to somehow pass these values ​​to the function:

 some_function (a,b, val1,val2,...,valn) 

I don’t want to write different versions of all these functions, but I suspect there is no other option?

+4
source share
4 answers

Variadic functions use a calling convention in which the caller is responsible for expressing function parameters from the stack, so yes, this can be done dynamically. It is not standardized in C and usually requires some assembly in order to manually press the necessary parameters and correctly use the variational function.

The cdecl calling cdecl requires the arguments to be inserted in the correct order, and after the call, the bytes passed as arguments before the call are returned. Thus, the called function can take an arbitrary number of parameters, since the calling party will process the return of the stack pointer to the state before the call. The space occupied by the arguments before ... is a safe lower bound for the number of bytes skipped. Additional variable arguments are interpreted at run time.

FFCALL is a library that provides wrappers for the dynamic transition of parameters to variational functions. A group of avcall features that interest you. Here is an example of calling the functions you specified above:

 #include <avcall.h> av_alist argList; int retVal; av_start_int(argList, some_function, retval); av_int(argList, a); av_int(argList, b); av_type(argList, val1); ... av_type(argList, valn); av_call(argList); 

You can also find this link by discussing the creation of wrappers around variational functions in C to interest in justifying why this is not part of the C standard.

+8
source

The standard approach is to ensure that each variational function is accompanied by a va_list forming copy (as in printf and vprintf). The Variadic version simply converts ... to va_list (using macros from stdarg.h ) and calls its sister va_list, which does the actual work.

+2
source

Perhaps it would be interesting to try just passing the array and then using vararg macros anyway. Depending on the alignment of the stack, it may just work (tm).

This is probably not the best solution, I basically posted it because I found this idea interesting. After testing, this approach worked on my Linux x86, but not on x86-64 - it can probably be improved. This method will depend on stack alignment, structure alignment, and possibly more.

 void varprint(int count, ...) { va_list ap; int32_t i; va_start(ap, count); while(count-- ) { i = va_arg(ap, int32_t); printf("Argument: %d\n", i); } va_end(ap); } struct intstack { int32_t pos[99]; }; int main(int argc, char** argv) { struct intstack *args = malloc(sizeof(struct intstack)); args->pos[0] = 1; args->pos[1] = 2; args->pos[2] = 3; args->pos[3] = 4; args->pos[4] = 5; varprint(5, *args); return 0; } 
+1
source

Depending on what you go through, it may be the discriminated union that you are here (as hinted at by the comments). This avoids the need for variational functions or void* arrays and answers the question β€œhow does some_function know what you really passed to it”. You might have code like this:

 enum thing_code { INTEGER, DOUBLE, LONG }; struct thing { enum thing_code code; union { int a; double b; long c; }; }; void some_function(size_t n_things, struct thing *things) { /* ... for each thing ... */ switch(things[i].code) { case INTEGER: /* ... */ } } 

You can do it even further and avoid switching by replacing code one or more pointers to functions that do something useful with each thing . For example, if you just want to print each item, you can get the following:

 struct thing { void (*print)(struct thing*); union { ... }; } void some_function(size_t n_things, struct thing *things) { /* .. for each thing .. */ things[i]->print(things[i]); /* ... */ } 
0
source

All Articles