I was wondering if there was any way to pass parameters dynamically to variadic functions. i.e. If I have a function
int some_function (int a, int b, ...){/*blah*/}
and I am accepting a bunch of values from the user, I want some way of passing those values into 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?
Variadic functions use a calling convention where the caller is responsible for popping the function parameters from the stack, so yes, it is possible to do this dynamically. It's not standardized in C, and normally would require some assembly to manually push the desired parameters, and invoke the variadic function correctly.
The cdecl calling convention requires that the arguments be pushed in the correct order, and after the call, the bytes pushed as arguments before the call are popped. In this way, the called function can receive an arbitrary number of parameters, as the caller will handle reverting the stack pointer to it's pre-call state. The space occupied by the arguments before the ... is the safe lower bound for number of bytes pushed. Additional variadic arguments are interpreted at runtime.
FFCALL is a library which provides wrappers for passing parameters dynamically to variadic functions. The group of functions you're interested in is avcall. Here's an example calling the functions you gave 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 might also find this link discussing generating wrappers around variadic functions in C, to be of interest in justifying why this isn't part of standard C.
A standard approach is to have each variadic function accompanied by a va_list-taking counterpart (as in printf and vprintf). The variadic version just converts ... to a va_list (using macros from stdarg.h) and calls its va_list-taking sister, which does actual work.
It might be interesting to try just passing an array, and then use the vararg macros anyway. Depending on stack alignment, it might Just Work (tm).
This is probably not an optimal solution, I mainly posted it because I found the idea interesting.
After trying it out, this approach worked on my linux x86, but not on x86-64 - it can probably be improved. This method will depend on stack alignment, struct alignment and probably 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;
}
Depending on what it is you're passing around, it could be a discriminated union you're after here (as hinted at in the comments). That would avoid the need for variadic functions or arrays of void*, and answers the question "how does some_function know what you actually passed it". You might have code something 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 take this a step further and avoid the switch by replacing the code with one or more pointers to functions that do something useful with each thing. For example, if what you wanted to do was to simply print out each thing, you could have this:
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]);
/* ... */
}
Related
Lets say I am maintaining an array of function structures in which I store API information.
This is definition of function structure:
typedef struct function {
void (*func)(long, ...);
char* name;
int argc;
char *argv[];
} function;
function api_list[N]
I would maintain a list of such structures.
Now given any function, I want to write a function Register(api_list, fp)
which adds one such structure initialized with details of function fp.
int fp(int a, int b) {
return a+b;
}
Register(api_list, fp);
How to do it in C?
I believe you will need to either parse the C function declarations yourself or find some other code to do it. I looked around a bit and there's code for this in the Ruby FFI, PerlXS and other script binding generators like SWIG. I also saw the XML plugin to GCC which generates XML describing the program.
If you look up C's BNF or EBNF definitions and know a bit of parsing theory, figuring out C functions is not hard. C++ is a whole other ball o' wax.
Note: I think I misunderstood. The following is for calling C functions with unknown number and types of arguments. Not for finding out what the function signature already looks like.
Look at the FFI (Foreign Function Interface) library which can be found at Sourceware:
https://sourceware.org/libffi/
This is packaged with many Linux systems already because it is heavily used by interpreted languages that need to call C functions.
Now given any function, I want to write a function Register(api_list, fp) which adds one such structure initialized with details of function fp.
There is no way to do this in Standard C. The main reason is you need keep track of original definition of an function to call it via such structure. You actually could store every function pointer as struct member:
void (*func)()
that is fine, but any attempt to call such function when type is not compatible (both parameters and return type are not the same) with original definition will invoke undefined behaviour. This means, that you would need to cast it properly for every call:
((int (*)(int, int)) api_list[0])(1, 2);
You may use GCC extensions typeof, but this method requires writing function's name (here fp) explicitely:
int result = ( (typeof(fp)*) api_list[0].func)(1, 2);
Even if you have stored somehow character string "fp" inside name member, there is no way to "connect" it with typeof, since it does not take string literals (well it takes, but not in the way you want) and in general there is no way to have it "destringized" as fp token.
Here is an illustration of above concepts:
#include <stdio.h>
typedef void (*GENERIC_FUNC_PTR)();
typedef struct function
{
GENERIC_FUNC_PTR func;
} function;
void Register(function *api_list, GENERIC_FUNC_PTR func)
{
api_list->func = func;
}
int add(int a, int b)
{
return a + b;
}
void print_message(void)
{
printf("%s\n", __func__);
}
int main(void)
{
function api_list[10];
Register(api_list, (GENERIC_FUNC_PTR) add);
Register(api_list + 1, (GENERIC_FUNC_PTR) print_message);
printf("%d\n", ( (typeof(add)*) api_list[0].func)(1, 2));
( (typeof(print_message)*) api_list[1].func)();
return 0;
}
I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) ¶m);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?
I am in a problem with a design question in C.
Let's say that I have a pretty large amount of functions, with different argument count.
POQ:
int print_one(int x)
{
printf("one: %d\n", x);
return 1;
}
int print_three(int x, int y, int z)
{
printf("three: %d-%d-%d\n", x, y, z);
return 3;
}
Now, I want to connect some properties to these functions in a structure, so that I can manipulate them without knowing the exact function, including their parameter count (I might even call the structure interface)
I tryd it like this, (& I think is pretty wrong):
typedef int (*pfunc)(int c, ...);
typedef struct _stroffunc
{
pfunc myfunction;
int flags;
int some_thing_count;
int arguments[10];
int argumentcount;
} stroffunc;
int main()
{
stroffunc firststruct;
firststruct.pfunc = (pfunc) print_two;
firststruct.something_count = 101;
arguments[0] = 102;
argumentcount = 1;
flag &= SOME_SEXY_FLAG;
// now I can call it, in a pretty ugly way ... however I want (with patially random results ofc)
firststruct.pfunc(firststruct.arguments[0]);
firststruct.pfunc(firststruct.arguments[0], 124, 11);
firststruct.pfunc(1, firststruct.arguments[0], 124, 1, 1);
}
I find this solution very ugly, & I think (hope) that there is a better solution for calling & and setting the function pointers.
I'm just hoping, that I was clear enough ...
NOTE: I didn't compile this code, but i compiled & run a very similar one so the concepts are working.
NOTE: pure C needed
Calling a non-variadic function through a variadic function pointer leads to undefined behaviour. For a start, recall that the arguments to variadic functions undergo the default argument promotions (chars are converted to ints, etc.), which will totally screw things up.
It's not clear how or why you intend to dynamically call a function with differing numbers of arguments. But one solution could be to use a union:
typedef struct {
int num_args;
union {
void (*f1)(int);
void (*f2)(int, int);
void (*f3)(int, int, int);
} func;
} magic;
...
magic m;
...
switch (m.num_args) {
case 1: m.func.f1(arg1); break;
case 2: m.func.f2(arg1, arg2); break;
case 3: m.func.f3(arg1, arg2, arg3); break;
default: assert(0);
}
A second solution would be to rewrite all of your functions as variadic.
This is on the edge of my knowledge, but I believe that you need to make the functions variadic as well, due to incompatibilities in the ABI.
see: wikipedia's example
Maybe you can add a library which have some functions to handle the struct, like a "pseudo" class,
int initFunc(int (*pfunc)(int c,...));
This function will save the pointer into the struct, like a context in POO, in the struct you will use it like a "map" of all the function an you will call each one using an id.
which returns an id, and you save it in an array,
then another func say
int call(int id,int p1,...);
where you say the function id and the parameters, sure you must now which function is each id
I have a 3rd party function with signature:
int secretfoo(int numargs, ...);
I can call it directly, but what I really want is wrap it with my function that adds some extra arguments to it.
Assume simple case of integers: I want calls secretfoo(2, 10, 20) to be translated as this: when I see argument 10 to duplicate it and make the call: secretfoo(3, 10, 10, 20). I want to do it in wrapper:
int foowrapper(int numargs, ...);
This wrapper analyze argumetns and call secretfoo as described above.
Can this be done in portably with va_list / va_arg etc.? Any other way?
There is no portable way to manipulate the arguments in a variable argument list directly, because it is highly platform dependent how such arguments are passed into the function. And on most hardware architectures, there is absolutely no way to insert additional arguments in the middle or the end of the list.
If there is a practical upper limit to the number of arguments, then it could be done by extracting all the arguments to foowrapper and 'manually' building the new argument list for the call to secretfoo.
The code would look something like this:
int foowrapper(int numarg, ...)
{
va_list args
int newargs[numarg*2]; /* worst case allocation */
int numnewargs = 0;
/* Extract the arguments */
va_start(numarg, args);
for (int i=0; i<numarg; i++)
{
newargs[numnewargs++] = va_arg(args, int);
/* duplicate value 10 as you encounter it */
if (newargs[numnewargs-1] == 10)
{
newargs[numnewargs++] = 10;
}
}
/* Forward to the secretfoo function */
switch (numnewargs)
{
case 0: return secretfoo(0);
case 1: return secretfoo(1, newargs[0]);
case 2: return secretfoo(2, newargs[0], newargs[1]);
/* etc... */
}
}
I'm afraid it can't be done portably. stdarg.h "defines four macros" (latest C standard draft): va_start, va_end, va_arg and va_copy. None of these can be used to convert a va_list back to a variable number of values, other than one-by-one.
Your third party library should have supplied a function vsecretfoo(int, va_list), like the standard library does for these cases (vprintf, etc.).
I've declared many functions in one driver, and am passing the pointers to the functions to another driver in a list with the node format:
struct node
{
char def_prototype[256]; //example:(int (*)(wchar, int, int))
void *def_function;
};
Is there a way to typecast def_function to the prototype given in def_prototype?
Currently I'm using simple switch and strcmp, but I wanted to generalize it if possible.
PS: I know that casting between void pointer and function pointer is unsafe (as mentioned in various places in SO), but desperate times call for desperate measures and I have taken lot of care.
EDIT:
Sorry for the lack in clarity. I want to actually call the function (not just cast it), making a function pointer at runtime based on the char[] provided.
EDIT AGAIN:
Since I'm working at the kernel level (windows driver), I don't have access to much resources, so, I'm sticking to my current implementation (with some changes to kill back-doors). Thanks to all for your help.
ISO-C does not allow casting between function and data pointers, ie you should use a void (*)(void) instead of a void * to hold your function.
That aside, YeenFei is correct in his assertion that there is no general platform-independant solution, meaning the best you can do in C itself is to supply a list of supported signatures.
You should implement your own encoding scheme instead of using plain C prototypes. It's common to use a string where each char represents a function argument (and the first one the return value); a function of type int (*)(wchar, int, int) for example could have the signature "iwii".
Signature lookup tables can then be easily built using bsearch() and strcmp(); here's a complete example:
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int cmp(const void *key, const void *element)
{
return strcmp(key, *(const char * const *)element);
}
static _Bool dispatch(const char *sig, void (*func)(void), void *retval, ...)
{
// supported signatures; must be ordered according to strcmp()
static const char * const SIGS[] = { "iii", "v", "vi" };
const char * const *match = bsearch(
sig, SIGS, sizeof SIGS / sizeof *SIGS, sizeof *SIGS, cmp);
if(!match) return 0;
va_list args;
va_start(args, retval);
switch(match - SIGS)
{
case 0: { // iii
int a1 = va_arg(args, int);
int a2 = va_arg(args, int);
int rv = ((int (*)(int, int))func)(a1, a2);
if(retval) memcpy(retval, &rv, sizeof rv);
break;
}
case 1: { // v
func();
break;
}
case 2: { // vi
int a1 = va_arg(args, int);
((void (*)(int))func)(a1);
break;
}
default:
assert(!"PANIC");
}
va_end(args);
return 1;
}
// example code:
static int add(int a, int b)
{
return a + b;
}
int main(void)
{
int sum;
dispatch("iii", (void (*)(void))add, &sum, 3, 4);
printf("%i", sum);
return 0;
}
unless you want to mess with assembly thunking (pushing data onto stack before jumping, etc), there is better way other than doing some switch case.
if the destination function is finite and known, why not create a lookup table (map<string, functor>) for it ?
A good implementation of similar ideas is libffi. This implements the gory details of declaring and calling functions with arbitrary calling conventions and signatures. It is (surprisingly) platform portable, and known to work on Linux and Windows out of the box.
An example of its use is the Lua extension library alien. That demonstrates calling arbitrary functions declared at runtime and adapting from native Lua types to the types required for the calling conventions. The specific Lua binding won't be useful to you, but it serves as a complete working example of how and why one might actually use libffi.
Since C has no runtime type information, there is absolutely no need to do a dynamic cast as you are considering. Just pass the pointer and if everything fits, it will work. If the pointer doesn't point to a function with the right signature, there is no way to fix it.
There are basically two solutions:
Go to the assembly level and parse the prototype string there and put the arguments you find in the prototype there where the other function will expect them.
Make a long list of all supported prototypes and compare the current one with the list. When you find a match, you can make the typecast as needed. The most common structure for this test would ba an if-else ladder.