Passing more parameters in C function pointers - c

Let's say I'm creating a chess program. I have a function
void foreachMove( void (*action)(chess_move*), chess_game* game);
which will call the function pointer action on each valid move. This is all well and good, but what if I need to pass more parameters to the action function? For example:
chess_move getNextMove(chess_game* game, int depth){
//for each valid move, determine how good the move is
foreachMove(moveHandler, game);
}
void moveHandler(chess_move* move){
//uh oh, now I need the variables "game" and "depth" from the above function
}
Redefining the function pointer is not the optimal solution. The foreachMove function is versatile and many different places in the code reference it. It doesn't make sense for each one of those references to have to update their function to include parameters that they don't need.
How can I pass extra parameters to a function that I'm calling through a pointer?

Ah, if only C supported closures...
Antonio is right; if you need to pass extra parameters, you'll need to redefine your function pointer to accept the additional arguments. If you don't know exactly what parameters you'll need, then you have at least three choices:
Have the last argument in your prototype be a void*. This gives you flexibility of passing in anything else that you need, but it definitely isn't type-safe.
Use variadic parameters (...). Given my lack of experience with variadic parameters in C, I'm not sure if you can use this with a function pointer, but this gives even more flexibility than the first solution, albeit still with the lack of type safety.
Upgrade to C++ and use function objects.

You'd probably need to redefine the function pointer to take additional arguments.
void foreachMove( void (*action)(chess_move*, int), chess_game* game )

If you're willing to use some C++, you can use a "function object":
struct MoveHandler {
chess_game *game;
int depth;
MoveHandler(chess_game *g, int d): game(g), depth(d) {}
void operator () (chess_move*) {
// now you can use the game and the depth
}
};
and turn your foreachMove into a template:
template <typename T>
void foreachMove(T action, chess_game* game);
and you can call it like this:
chess_move getNextMove(chess_game* game, int depth){
//for each valid move, determine how good the move is
foreachMove(MoveHandler(game, depth), game);
}
but it won't disrupt your other uses of MoveHandler.

If I'm reading this right, what I'd suggest is to make your function take a pointer to a struct as an argument. Then, your struct can have "game" and "depth" when it needs them, and just leave them set to 0 or Null when you don't need them.
What is going on in that function? Do you have a conditional that says,
if (depth > -1) //some default
{
//do something
}
Does the function always REQUIRE "game" and "depth"? Then, they should always be arguments, and that can go into your prototypes.
Are you indicating that the function only sometimes requires "game" and "depth"? Well, maybe make two functions and use each one when you need to.
But, having a structure as the argument is probably the easiest thing.

I'd suggest using an array of void*, with the last entry always void.
say you need 3 parameters you could do this:
void MoveHandler (void** DataArray)
{
// data1 is always chess_move
chess_move data1 = DataArray[0]? (*(chess_move*)DataArray[0]) : NULL;
// data2 is always float
float data1 = DataArray[1]? (*(float*)DataArray[1]) : NULL;
// data3 is always char
char data1 = DataArray[2]? (*(char*)DataArray[2]) : NULL;
//etc
}
void foreachMove( void (*action)(void**), chess_game* game);
and then
chess_move getNextMove(chess_game* game, int depth){
//for each valid move, determine how good the move is
void* data[4];
data[0] = &chess_move;
float f1;
char c1;
data[1] = &f1;
data[2] = &c1;
data[3] = NULL;
foreachMove(moveHandler, game);
}
If all the parameters are the same type then you can avoid the void* array and just send a NULL-terminated array of whatever type you need.

+1 to Antonio. You need to change your function pointer declaration to accept additional parameters.
Also, please don't start passing around void pointers or (especially) arrays of void pointers. That's just asking for trouble. If you start passing void pointers, you're going to also have to pass some kind of message to indicate what the pointer type is (or types are). This technique is rarely appropriate.
If your parameters are always the same, just add them to your function pointer arguments (or possibly pack them into a struct and use that as the argument if there are a lot of parameters). If your parameters change, then consider using multiple function pointers for the multiple call scenarios instead of passing void pointers.

If your parameters change, I would change the function pointer declaration to use the "..." technique to set up a variable number of arguments. It could save you in readability and also having to make a change for each parameter you want to pass to the function. It is definately a lot safer than passing void around.
http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html
Just an FYI, about the example code in the link: some places they have “n args” and others it is “n_args” with the underscore. They should all have the underscore. I thought the syntax looked a little funny until I realized they had dropped the underscore in some places.

Use a typedef for the function pointer. See my answer for this question

Another option would be to modify the chess_move structure instead of the function prototype. The structure is presumably defined in only one place already. Add the members to the structure, and fill the structure with appropriate data before any call which uses it.

Related

Typecasting for functions with different arguments in c

So I have two functions that does the same thing but on different type variables.
The first function fills up an array of integers when given an int arr[] argument.
The second function fills up a linked list with integers also when given a struct as an argument.
The struct for the linked list argument looks something like this
typedef struct {node_t *head;int size;}
list_t;
Now I have implemented a table of function pointers for the two functions as such:
typedef struct{
char *name; //name of the function
void (*fill)(int arr[]); //fill up the array
} alg_t;
alg_t algs[] = {
{"func1",fill_up_arr},
{"func2",fill_up_linkedList}
};
Notice that inside the struct that holds my pointers, the fill function pointer
takes int arr[] as an argument.
I only want one pointer of a function in that struct, is there a way I can use
typecasting so that other functions such as fill_up_linkedList require argument to be of type list_t instead of int arr[]?
//This is what I want my main to look like.
//I want func.fill to be called only once thus
//dynamically perform the operations for all functions inside the table of
//functions array
int arr = malloc(sizeof(int)algs.size);
for(int i = 0; i<algs.size;i++){
alg_t func = algs[i];
func.fill(arr);
}
It seems that the problem with this code would be when the loop would try and perform the fill_up_LinkedList function as it needs a different argument.
How can I use a typecast in this situation?
Thanks
The good news
C11 §6.3.2.3 Pointers ¶8 (under the general topic §6.3 Conversions) says:
A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer. If a converted
pointer is used to call a function whose type is not compatible with the referenced type,
the behavior is undefined.
That means you can store any and all function pointers in a common function pointer type, for example typedef void (*GenericFunctionPointer)(void). What is crucial, though, is that you convert from that generic function pointer type back to the correct function pointer type before you invoke the function via the pointer (and that you provide the correct argument list, and that you handle the return type appropriately, though ignoring the return value, if any, is always an option).
The bad news
For two different function pointer types, each with one instance of the the function, the infrastructure needed to support this is probably more elaborate than the savings, if any. On the other hand, if you have two or more different function pointer types, and most if not all of the types have many representative functions ('many' meaning 'more than one', as in the computer engineer's counting: "zero, one, many"), then the infrastructure can pay off. One of the issues is marshalling the function arguments — how are the arguments made accessible so that the function can be called via the pointer with the correct arguments.
So, doing things this way is complex and verbose.
The stated requirement
In a comment, the OP Moi says:
I only want to put one function in the struct. My goal is to find a way to allow fillArray to allow the passing of different args.
I have major reservations about the use of an uncounted array as the argument list as shown in the question — void (*fill)(int arr[]) is shown. In my view, it should be void (*fill)(size_t n, int arr[n]), using the variable length array notation. You can omit the n in the subscript if you wish — void (*fill)(size_t n, int arr[]) — or even use void (*fill)(int arr[], size_t n), which is the more classic order for the arguments.
Putting this concern aside, if you want a single function to accept different arguments, one way to achieve that is with void * as the type, but you have to be aware of the problems — one of which is type safety. You'll also need to borrow ideas from the standard C functions qsort() and bsearch(). The argument list will include the pointer to the start of the array as a void *, the size of each element of the array, and the number of elements in the array. You may also need analogues to the comparator functions.
Internal to the single called function, though, you will probably end up with two code paths, so although you call a single function via the pointer, you end up doing the equivalent of implementing two functions. You could use an interface similar to qsort()'s so that the two functions have the same interface and different bodies, and you use two pointers in the alg_t array.
Summary
You probably can't achieve the stated requirement cleanly.
You will probably need two logically separate functions to handle the two separate interfaces, even if you smush all the code inside a single function.
Use a union:
typedef struct {
char *name; //name of the function
union {
void(*fillArray)(int arr[]); //fill up the array
void(*fillList)(YourListType list); //fill up the list
};
} alg_t;
alg_t a;
a.fillArray(...);
a.fillList(...);
Or:
typedef struct {
char *name; //name of the function
union {
void(*fillArray)(int arr[]); //fill up the array
void(*fillList)(YourListType list); //fill up the list
} functions;
} alg_t;
alg_t a;
a.functions.fillArray(...);
a.functions.fillList(...);
Since you only have 2 types, you can just use an enum and a macro
enum e_type {e_foo,e_bar};
#define do_foobar(e,...) (e)?bar(__VA_ARGS__):foo(__VA_ARGS__)
replace foo and bar with your function names
If you only have the problem with the function parameters and not with the return value, there's a trick related to incomplete type definitions. The trick consists in leaving empty the list of parameters in the pointer type declaration, as in:
typedef void (*callback_ptr)();
which is different from:
typedef void (*callback_ptr)(void);
in the first case, the compiler will not check the parameters passed to the function, as the pointer is a pointer to an incompletely defined function type, while the second explicitly says the function doesn't require parameters and will give you an error if you try to call it with them.

Defining a function as a function pointer

Mostly for fun, I've decided to write my own minimal test framework for my C code. I use a basic struct for the test information, create an array of test structs and then iterate over them to run all the tests. This amounts to a very small amount of work for a fairly elegant (imho) solution.
However, the one thing that is a little annoying is that I cannot figure out how to define functions as function pointers instead of defining the function and then creating a function pointer later.
I have the following (which works just fine):
typedef int (* test_p) (void);
struct test {
char * desc;
test_p func;
};
int
example_test (void) {
puts("This is a test");
return 0;
}
void
run_test (char * test_name, test_p test) {
printf("Testing %s\t\t\t[ PEND ]\r", test_name);
char * test_result = (test() ? "FAIL" : "PASS");
printf("Testing %s\t\t\t[ %s ]\n", test_name, test_result);
}
int
main (void) {
struct test test_list [] = {
{ "example test", (test_p )example_test }
};
for ( int i = 0; i < 1; i ++ ) {
run_test(test_list[i].desc, test_list[i].func);
}
return 0;
}
However, I am hoping I can remove the need for the casting in the struct and instead define the function as being a function pointer from the beginning. The following is an example of how I would like this to work (assuming many of the same things as above):
test_p
example_test = {
puts("This is a test");
return 0;
}
If I could do something like this, then in the struct, I could simply have the func field be example_test rather than (test_p )example_test. Is this (or something like it) possible? If not, is there a reason why not (If that reason is simply "because it wasn't added to the language", that's fine)?
A function pointer is one kind of thing and a function is another kind of thing so you can't really make the latter be the former. But if you use a function name where a function pointer is expected, that produces a pointer to the function, so you can just remove the unnecessary cast, as WhozCraig said in the first comment above. You write
If I could do something like this, then in the struct, I could simply have the func field be example_test rather than (test_p )example_test.
You can do that, with example_test defined just as it is in your current code ... did you try that?
You can also forward declare a function, like so:
typedef int test_func(void); // note no indirection
typedef test_func* test_p;
test_func example_test;
It would be nice if you could use that sort of syntax when you define the function, as in your attempted syntax, but there's simply no way to do that in C ... you have to explicitly provide the return type and parameter list.
Another detail is that, when you invoke the function pointed to by a function pointer, you don't have to dereference it ... that's why you were able to write
test()
instead of
(*test)()
although the latter also works. (In fact, because the deference is stripped, (********test)() also works ... but only do that if you're trying to win an obfuscation contest.)
What you are describing is a kind of meta-programming. Rather than writing code to explicitly solve the problem, you are concerned with a kind of syntactic structure that will allow you to define a whole raft of test functions without unnecessary cruft.
In Lisp you would use macros. In C++ you might use templates and/or lambdas. In C you use macros.
So you need to write a macro that:
takes a name and descriptive text as arguments
defines a static variable of type function (created from that name using token pasting)
defines a function (using a name created by token pasting)
[edit] At this point you have achieved the goal: you have created the function and given it a name that is (only) a function pointer, and you can use that name in your struct without a cast. I would suggest one additional step, the macro also:
adds the variable/function and descriptive text to a list of functions to be tested.
Then your boilerplate loop iterates over the structure calling each function and reporting the results using the descriptive text. Problem solved.
Some people don't like macros, but they are ideally suited to this situation, and there is no other way to do it in C. I did something just like this before making the move to C++.

Passing structure with list of structures to function

I have a function with prototype:
void procedureForEachWave(struct barge *Barge, struct settings *Settings, struct wave *Wave)
In another function I have a another structure called threadData, which I use to send information to functions that run on several threads, and one of the element of this structure is a list of struct wave, so the short vesion of this code goes:
struct threadData data;
data.waveList = (struct wave*) malloc(sizeof(struct wave)*nrOfWaves);
I use this in another function, where I basically first send a pointer to the structure data, and then inside this function the "procedureForEachWave" function is called in a loop like this:
procedureForEachWave(data->Barge, data->Settings, &data->waveList[i]);
This works fine. However, I also want to do an analysis where I only use one wave, meaning that the list only contains one element, and I therefore don't need to call the first function. I only want to do this:
procedureForEachWave(Barge, Settings, &data.waveList[0]);
but this does not work. Why? and how do I get it to work? To clarify, data is now declared as a variable, not a pointer, and Barge and Settings are pointers already. The waveList is declared like this:
data.waveList = (struct wave*) malloc(sizeof(struct wave));
Without knowing ANYTHING about what is going on inside of procedureForEachWave, it is difficult (if not impossible) to tell what the problem is.
However, it does look like data is being used differently between the call that works and the one that doesn't. If they are using the same data, the call should be the same (substituting 0 for i). If they are different, please provide a definition of this other data.
Consider the code fragment:
extern void wave_function(struct wave *);
struct wave value = { ... };
struct wave array[10] = { { ... } };
wave_function(&value);
wave_function(array);
wave_function(&array[5]);
The called function cannot tell from the pointer it was given whether it was passed a pointer to a single value or a pointer to an array of values. The calling function and the called function must agree on how the pointer will be used, perhaps by including the number of elements in the array as a separate argument:
extern void alt_wave_function(struct wave *, size_t);
alt_wave_function(&value, 1);
alt_wave_function(array, 10);
alt_wave_function(&array[5], 3);
Note that if the size passed with the pointer &value was larger than 1, you'd be into undefined behaviour. The other two calls are both wholly legitimate: the third one, though, effectively passes a three-row subset of the array to the function.
So, inside a function, any pointer argument can be treated as a pointer to a single value, or as the pointer to the first item in an array of values. Both are correct. Indeed, you can even write:
void wave_function(struct wave *ptr)
{
}
void wave_function(struct wave ptr[])
{
}
These are equivalent declarations (but only in the argument list). You can even include a size in the array notation, though that conveys no information to the function, unless you dress it up in C99 syntax:
void wave_function(struct wave array[static 4])
{
}
This notation means that the caller must guarantee that there are at least 4 elements in the array passed to this version of wave_function.

How to check if a void* pointer can be safely cast to something else?

Let's say I have this function, which is part of some gui toolkit:
typedef struct _My_Struct My_Struct;
/* struct ... */
void paint_handler( void* data )
{
if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */
{
My_Struct* str = (My_Struct*) data;
}
}
/* in main() */
My_Struct s;
signal_connect( SIGNAL_PAINT, &paint_handler, (void*) &s ); /* sent s as a void* */
Since the paint_handler will also be called by the GUI toolkit's main loop with other arguments, I cannot always be sure that the parameter I am receiving will always be a pointer to s.
Can I do something like IS_MY_STRUCT in the paint_handler function to check that the parameter I am receiving can be safely cast back to My_Struct* ?
Your void pointer looses all its type information, so by that alone, you cannot check if it can be cast safely. It's up to the programmer to know if a void* can be cast safely to a type.
Unfortunately there is no function to check what the pointer was before it appears in that context (void).
The one solution I can think of is if you place an int _struct_id as the first member of all of your structs. This id member can then be safely checked regardless of the type but this will fail if you pass pointers that don't implement this member (or int, char, ... pointers).
The best you could do would be to look at what data points to to see if it has telltale signs of being what you want, although a) it wouldn't be anywhere close to a guarantee and b) might be dangerous, as you don't know how big the thing data actually points to is. I suppose it isn't any more dangerous than just casting it and using it, but (as has been suggested) a redesign would be better.
If you are creating the type that is being used, you could include as part of the type some kind of identifying information that would help you rule out some void pointers as not being of the type you are looking for. While you would run the chance that some random area of memory would contain the same data or signature as what you are looking for, at least you would know when something was not the type you were looking for.
This approach would require that the struct was initialized in such a way that the signature members, used to determine if the memory area is not valid, is initialized to the signature value.
An example:
typedef struct {
ULONG ulSignature1;
// .. data elements that you want to have
ULONG ulSignature2;
} MySignedStruct;
#define MYSIGNEDSTRUCT_01 0x1F2E3D4C
#define MYSIGNEDSTRUCT_02 0xF1E2D3C4
#define IS_MY_STRUCT(sAdr) ( (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_01 ) && (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_02))
This is kind of a rough approach however it can help. Naturally using a macro like IS_MY_STRUCT() where the argument is used twice can be problematic if the argument has a side effect so you would have to be careful of something like IS_MY_STRUCT(xStruct++) where xStruct is a pointer to a MySignedStruct.
There really isn't in c. void pointers are typeless, and should only ever be casted when you truly know what they point to.
Perhaps you should instead reconsider your design; rewrite your code so that no inspection is necessary. This is the same reason google disallows RTTI in its style guide.
I know the question is 3 years old but here I go,
How about using a simple global enum to distinguish where the function is called from. then you can switch between what type to cast the void pointer to.

What does ... mean in an argument list in C?

I came across the following function signature and I wondered if this (the ellipsis, or "...") is some kind of polymorphism?
#include <fcntl.h>
int fcntl(int fd, int cmd, ... );
Thanks in advance.
It's a variable argument list.
That is a variadic function. See stdarg.h for more details.
The ... means that you can pass any number of arguments to this function, as other commenters have already mentioned. Since the optional arguments are not typed, the compiler cannot check the types and you can technically pass in any argument of any type.
So does this mean you can use this to implement some kind of polymorphic function? (I.e., a function that performs some operation based on the type of its arguments.)
No.
The reason you cannot do this, is because you cannot at runtime inspect the types of the arguments passed in. The function reading in the variable argument list is expected to already know the types of the optional arguments it is going to receive.
In case of a function that really is supposed to be able to take any number of arguments of any type (i.e., printf), the types of the arguments are passed in via the format string. This means that the caller has to specify the types it is going to pass in at every invocation, removing the benefit of polymorphic functions (that the caller doesn't have to know the types either).
Compare:
// Ideal invocation
x = multiply(number_a, number_b)
y = multiply(matrix_a, matrix_b)
// Standard C invocation
x = multiply_number(number_a, number_b)
y = multiply_matrix(matrix_a, matrix_b)
// Simulated "polymorphism" with varargs
x = multiply(T_NUMBER, number_a, number_b)
y = multiply(T_MATRIX, matrix_a, matrix_b)
You have to specify the type before the varargs function can do the right thing, so this gains you nothing.
No, that's the "ellipsis" you're seeing there, assuming you're referring to the ... part of the declaration.
Basically it says that this function takes an unknown number of arguments after the first two that are specified there.
The function has to be written in such a way that it knows what to expect, otherwise strange results will ensue.
For other functions that support this, look at the printf function and its variants.
Does C support polymorphism?
No, it doesn't.
However there are several libraries, such as Python C API, that implements a rough variant of polymorphism using structs and pointers. Beware that compiler cannot perform appropriate type checking in most cases.
The tecnhique is simple:
typedef struct {
char * (*to_string)();
} Type;
#define OBJ_HEADER Type *ob_type
typedef struct {
OBJ_HEADER;
} Object;
typedef struct {
OBJ_HEADER;
long ival;
} Integer;
typedef struct {
OBJ_HEADER;
char *name;
char *surname;
} Person;
Integer and Person get a Type object with appropriate function pointers (e.g. to functions like integer_to_string and person_to_string).
Now just declare a function accepting an Object *:
void print(Object *obj) {
printf("%s", obj->type->to_string());
}
now you can call this function with both an Integer and a Person:
Integer *i = make_int(10);
print((Object *) i);
Person *p = make_person("dfa");
print((Object *) p);
EDIT
alternatively you can declare i and p as Object *; of course make_int and make_person will allocate space for Integer and Person and do the appropriate cast:
Object *
make_integer(long i) {
Integer *ob = malloc(sizeof(Integer));
ob->ob_type = &integer_type;
ob->ival = i;
return (Object *) ob;
}
NB: I cannot compile these examples rigth now, please doublecheck them.
I came across the following function signature and I wondered if this (the ellipsis, or "...") is some kind of polymorphism?
yes, it is a primitive form of polymorphism. With only one function signature you are able to pass various structures. However the compiler cannot help you with detecting type errors.
Adding to what's been said: C supports polymorphism through other means. For example, take the standard library qsort function which sorts data of arbitrary type.
It is able to do so by means of untyped (void) pointers to the data. It also needs to know the size of the data to sort (provided via sizeof) and the logic that compares the objects' order. This is accomplished by passing a function pointer to the qsort function.
This is a prime example of runtime polymorphism.
There are other ways to implement object-oriented behaviour (in particular, virtual function calls) by managing the virtual function tables manually. This can be done by storing function pointers in structures and passing them around. Many APIs do so, e.g. the WinAPI, which even uses advanced aspects of object orientation, e.g. base class call dispatch (DefWindowProc, to simulate calling the virtual method of the base class).
I assume you are referring to the ellipsis (...)? If so this indicates that 0 or more parameters will follow. It is called varargs, defined in stdarg.h
http://msdn.microsoft.com/en-us/library/kb57fad8.aspx
printf uses this functionality. Without it you wouldn't be able to keep adding parameters to the end of the function.
C supports a crude form of Polymorphism. I.e. a type being able to appear and behave as another type. It works in a similar was as in C++ under the hood (relying on memory being aligned) but you have to help the compiler out by casting. E.g. you can define a struct:
typedef struct {
char forename[20];
char surname[20];
} Person;
And then another struct:
typedef struct {
char forename[20];
char surname[20];
float salary;
char managername[20];
} Employee;
Then
int main (int argc, int *argv)
{
Employee Ben;
setpersonname((Person *) &Ben);
}
void setpersonname(Person *person)
{
strcpy(person->forename,"Ben");
}
The above example shows Employee being used as a Person.
No, it is a function that is taking variable number of arguments.
That is not technically polymorphism. fcntl takes variable number of arguments & that is the reason for the ... similar to printf function.
C neither supports function overloading - which is a type of ad-hoc polymorphism based on compile-time types - nor multiple dispatch (ie overloading based on runtime types).
To simulate function overloading in C, you have to create multiple differently named functions. The functions' names often contain the type information, eg fputc() for characters and fputs() for strings.
Multiple dispatch can be implemented by using variadic macros. Again, it's the programmer's job to provide the type information, but this time via an extra argument, which will be evaluated at runtime - in contrast to the compile-time function name in case of the approach given above. The printf() family of functions might not be the best example for multiple dispatch, but I can't think of a better one right now.
Other approaches to multiple dispatch using pointers instead of variadic functions or wrapping values in structures to provide type annotations exist.
The printf declaration in the standard library is
int printf(const char*, ...);
Think about that.
You can write code that supports Polymorphic behavior in C, but the ... (ellipsis) is not going to be much help. That is for variable arguments to a function.
If you want polymorphic behavior you can use, unions and structures to construct a data structure that has a "type" section and variable fields depending on type. You can also include tables of function pointers in the structures. Poof! You've invented C++.
Yes C Do support the polymorphism
the Code which we write in the C++ using virtual to implement the polymorphism
if first converted to a C code by Compiler (one can find details here).
It's well known that virtual functionality in C++ is implemented using function pointers.

Resources