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
Related
I am writing some tests for my project, and the functions have the same return type but a different number of parameters. I want to use an array of function pointers to call these test functions. How to declare an array of function pointers for such functions?
The functions are declared as:
bool test1();
bool test2(char const *string, uint32_t length);
Consider that function pointers are not magic tricks, they still have to abide to the ABI calling convention, meaning that a function with a certain signature is intrinsically different from a function with a different signature.
Using a function pointer is more of a way to have dynamic methods, than to achieve polymorphism. EDIT: This is not polymorphism.
However, you can accomplish somewhat you ask by replacing each of the test functions to accept a void* and then code your parameters in a struct.
// Declare the test functions
//bool test1();
bool test1(void* struct_address)
{
// struct address unused.
}
// Parameters for test2
struct test2{
char const* string;
uint32_t* length;
}
//bool test2(char const *string, uint32_t length);
bool test2(void* struct_address)
{
struct test2 test2_s = *(struct test2*)(struct_address);
// Work with test2_s
}
// Declare the function pointer
bool (*test_ptr)(void *);
// call test1
test_ptr = test1; test_ptr((void*)NULL);
// call test2
struct test2 test2_s = {param1,param2};
test_ptr = test2; test_ptr((void*)&test2_s);
Be careful because if you pass the wrong struct type you will get memory leaks and segmentation errors. Since this is a test environment, however, this can be mitigated.
In C, an empty parameter list in a function declaration does not mean that the function takes no argument; rather, it means that it takes an unspecified number of arguments.1
So, syntactically at least, you can specify an array of function pointers, each with an unspecified number of arguments (but a fixed return type), like this: bool (*FnPtrArray[100])();. You can then assign, to different elements of such an array, addresses of functions with different argument types and numbers. However, there can then be no compile-time check that those functions are called correctly, or any implicit conversion of given argument types to the 'correct' forms.
The code below illustrates this (but note that I do not recommend using code like this, because of the inherent dangers that passing incorrect arguments can cause):
#include <stdio.h>
#include <stdbool.h>
bool Foo(int a) {
printf("Foo: %d ...\n", a);
return a % 2;
}
bool Bar(double x, double y) {
printf("Bar: %5.3lf %5.3lf...\n", x, y);
return x < y;
}
int main()
{
bool (*FnPtrArray[100])();
// So we can't tell at compile time which elements point where ...
printf("Enter a number: ");
int n = 42;
scanf("%d", &n);
if (n % 2) {
FnPtrArray[0] = Foo;
FnPtrArray[1] = Bar;
}
else {
FnPtrArray[1] = Foo;
FnPtrArray[0] = Bar;
}
// Notes assuming given "n" is odd ...
printf("%d\n\n", FnPtrArray[0](3)); // Works
printf("%d\n\n", FnPtrArray[0](3.0)); // Wrong argument type
printf("%d\n\n", FnPtrArray[1](1.0, 2.0)); // Works
printf("%d\n\n", FnPtrArray[1](1, 2)); // Wrong argument types
printf("%d\n\n", FnPtrArray[1](1.0)); // Wrong number of args
return 0;
}
Here's a link to the above code on Compiler Explorer, for those who want to test with various compilers and settings.
1 This is very different from C++, where an empty formal parameter list does mean no argument.
In C, I am trying to pass a single-variable function into an optimization routine (optimization_routine). The optimization routine takes as input a pointer func1ptr to a function of a single float variable. However, I need to be able to pass multiple variables into this function. Thus, I am trying to construct a function pointer of one variable where all but the first inputs are "constants" into the function variable (sort of analogous to a partial derivative in calculus). I think I can do this with function pointers, but I can't figure out a syntax that makes sense.
That is, I have a function like this:
float function_all_inputs( float A, int B, float C, char D);
The optimization function requires a pointer like this:
typedef (*func1ptr)(float);
void optimization_function( func1ptr fp );
Thus, I want to construct a function of this form:
// create a function of A only at runtime using inputs B,C,D
func1ptr fp = ( & function_all_inputs(A,B,C,D))(A);
The function pointed to by fp should have the signature:
float function_one_input(float A);
Inputs B, C, and D are calculated elsewhere in the code, and thus are not known at compile-time; however, they are constant inside optimization_function.
I think I can do this in pure C using function pointers, however, I can't figure out the correct syntax. None of the examples I found online cover this case. Any advice you can provide would be appreciated.
It sounds like you are asking how to create a closure to capture parameters in C, and you can take a look at some options in the linked question.
However, without custom extensions, I think you will need to use global variables to achieve the effect you are looking for.
// Pass this wrapper with the name "wrapper" into the function
// that requires a function pointer
void wrapper(float a) {
// Where last four arguments are global variables that are computed first.
function_all_inputs(a, b, c, d, e);
}
// No need to create an explicit function pointer.
// Passing the name of the function is sufficient.
optimization_function(wrapper);
You need to write a wrapper function, like
int b;
float c;
char d;
int wrap(float a) {
return function_all_inputs(a, b, c, d);
}
Consider concurrency an re-entrancy though:
If multiple threads can use the wrapper, and need it to pass different data, make those globals thread-local:
_Thread_local int b;
If you need full re-entrancy, things get complicated:
You need to (also) save the variables before using a nested invocation with different parameters.
Writing a second (and maybe third) version of the wrapper using different globals may be better.
If you need more active at the same time, you can try a pool of those functions, though it gets unwieldy really fast. Better change your optimization-function by adding a context-parameter, and pass those extra-parameters with that.
For full freedom, you really need a way to write functions at runtime, at least enough to recover a context-pointer. That's not possible in pure C though.
If sizeof(float) >= sizeof(void*) on your platform, then you can "hack" it as follows:
typedef struct
{
float a;
int b;
float c;
char d;
}
params;
int function_all_inputs(float a, int b, float c, char d)
{
...
}
int function_one_input(float f)
{
params* p;
memcpy((void*)&p, (void*)&f, sizeof(void*));
return function_all_inputs(p->a, p->b, p->c, p->d);
}
int optimize()
{
float f;
params v;
params* p = &v;
v.a = ...;
v.b = ...;
v.c = ...;
v.d = ...;
memcpy((void*)&f, (void*)&p, sizeof(void*));
return optimization_function(function_one_input, f);
}
You weren't very consistent in your question about the return-value type, so I used int.
This may be overkill, but libffi supports creating closures in the following way:
#include <stdio.h>
#include <ffi.h>
typedef struct BCD { int B; float C; char D; } BCD;
void function_one_input_binding
(ffi_cif* cif, int* result, void** args, BCD* bcd) {
*result = function_all_inputs(*(float*)args[0], bcd->B, bcd->C, bcd->D);
}
int main() {
ffi_cif cif;
ffi_type* args[1];
ffi_closure* closure;
int (*function_one_input)(float);
// Allocate a closure.
closure = ffi_closure_alloc(sizeof(ffi_closure), &function_one_input);
// Tell libffi the parameter and return types.
args[0] = &ffi_type_float;
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_int, args);
// Bind closure data.
BCD bcd = { .B = 1, .C = 2.5, .D = 'x' };
ffi_prep_closure_loc(
closure, &cif, function_one_input_binding, &bcd, function_one_input);
// Call the function.
int result = function_one_input(42.5);
// Free the allocated closure.
ffi_closure_free(closure);
return 0;
}
I know function call back is embedding another function pointer in the call of another function like this:
Function Declaration:
function_call_back(int x, int y, void (*functonPtr)(int x, char y , struct newStruct* sptr))
void func(int x , char y , struct newStruct* sptr1)
{
//perform Algorithm 1 on x,y ,sptr1
}
void func2(int x , char y , struct newStruct* sptr2)
{
//perform Algorithm 1 on x,y ,sptr2
}
void func3(int x , char y , struct newStruct* sptr3)
{
//perform Algorithm 1 on x,y ,sptr3
}
void func4(int x , char y , struct newStruct* sptr4)
{
//perform Algorithm 1 on x,y ,sptr4
}
main()
{
// function calling
function_call_back(23, 2256, func1);
}
Here the third argument is func, as function name is equivalent to function pointer
I agree that the func here can be altered with different variation of similar function signature by adding this line in main above before call to function_call_back:
typedef void (*fptr)(int int x , char y , struct newStruct* ptr);
fptr f1 = func2; // or func3, or func4
function_call_back(23, 2256, f1);
The third argument is func, as function name is but I was wondering this can be achieved in the below way also, by simply adding the function-calling code in the call to function_call_back:
function_call_back(23, 2256, functionCallingcode); //third argument is func
The new declaration of function_call_back is:
function_call_back(int x, int y, int functionCallingCode)
And its new definition is:
void function_call_back(int x, int y, int functionCallingCode)
{
switch(functionCallingCode)
case 1:
func1(1,"g",sptr1);
break;
case 2:
func2(1,"c",sptr2);
break
case 3:
func3(1,"d",sptr3);
break;
case 4 :
func4(1,"s",sptr4);
break ;
default :
printf("Wrong Function calling code");
}
}
Then why to use function pointer?
With the switch statement, you can call every function that you choose to code into your callback function. You are guaranteed that only one of your known collection of functions can be called.
With the function pointer, you can call any function that you may define at a later and completely unrelated point in your development. You're free to define and use any callback function with a matching signature.
In other words, the switch allows you to branch among a bounded set of choices, while the function pointer gives you unbounded flexibility. Usually there's little reason to prefer anything else over the function pointer.
They are not better, they are practically the only option you have.
You can do this switch, but in the same approach, you can just write the whole program in one functions. Functions are there to separate code units, and this "switch-function" just units too many things.
In the case you describe you clearly can get the functionality you want without using a function pointer.
However consider what happens if you want to add the option of func5 in a few weeks time. And then as time goes by you want to add func6, func7, ..., func10, func20. function_call_back() gets bigger and messier whereas with the function pointer version you can add as many different funcs as you want without having to edit function_call_back() at all.
The function pointer implementation also gives you the flexibility to parcel function_call_back() up as part of a library that you or anyone else can use in another program without having to mess with, or even have, the source code. See the standard library qsort function for an example of why this is really handy.
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.
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]);
/* ... */
}