Reputation: 24602
I'm writing a unit test framework (see SO for more details). Or view the code at GitHub.
Safer Code describes a way to pass functions of arbitrary types.
But how do I call such a function without knowing its types beforehand? Assume f
needs no input, so f()
should work on its own.
Let's say I want to populate an array using an arbitrary generator function.
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = gen(NULL);
}
return arr;
}
It should look something like this, but I get compiler errors:
gcc -o example example.c qc.c qc.h -lgc
In file included from example.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
In file included from qc.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
qc.c:23: error: conflicting types for ‘gen_array’
qc.h:21: error: previous declaration of ‘gen_array’ was here
qc.c: In function ‘gen_array’:
qc.c:29: warning: dereferencing ‘void *’ pointer
qc.c:29: error: too many arguments to function ‘gen’
qc.c:29: error: invalid use of void expression
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
make: *** [example] Error 1
Upvotes: 2
Views: 1519
Reputation: 637
For the case where your pointer to a function 'fp' is of type which takes no argument and returns void, in which case you should declare it as :
typedef void (*fp)();
In the above case the call should be :
(*gen)();
If your pointer to the function 'fp' is of type which takes 'void *' as argument and returns void, in which case you should declare it as :
typedef void (*fp)(void *);
In the above case the call should be :
(*gen)(NULL);
or any other pointer variable you might want to pass.
As far as your example goes try this :
typedef void * (*fp)(void *);
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = (*gen)(NULL);
}
return arr;
}
Upvotes: 0
Reputation: 1180
After thinking about some more I realize your problem your above code would never work. You are first calling trying to call a void function with no parameters with the parameter NULL. Next you would need your code to be more generic. I placed an example below of what I mean. Now using a global variable
#include <stdio.h>
#include <stdlib.h>
typedef void (*fp)(void);
void * GEN_ARRAY_TEMP;
int gen_int() {
return 67;
}
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = malloc(len * size);
void* arr_end = arr + len * size;
GEN_ARRAY_TEMP = arr;
while (GEN_ARRAY_TEMP <= arr_end) {
gen();
GEN_ARRAY_TEMP+=size;
}
return arr;
}
void make_int() {
(*(int*)GEN_ARRAY_TEMP) = 9;
}
int main() {
int i;
int * gen_int_array = (int*) gen_array(make_int, sizeof(int));
for(i=0;i<67;i++) {
printf("%d\n",gen_int_array[i]);
}
}
Upvotes: 1
Reputation: 231063
You have two problems:
First, qc.h
is missing a <stdlib.h>
include. This is needed for use of size_t
.
Second, in gen_array
, you create a void *arr
, then try to dereference it as an array (arr[i]
). Since the compiler doesn't know the size of your array elements, it cannot fill the array. You must treat it as a char *
, offset by arr + size * i
, and pass it into gen
rather than taking a return (returns also need to know the structure size):
// ...
char *arr = GC_MALLOC(len * size);
for (int i = 0; i < len; i++) {
gen(arr + i * size, NULL);
}
return arr;
This will of course require changing the fp
type definition.
Upvotes: 0
Reputation: 471209
That page suggests you make the function pointer take a void*
. So in order for your code to compile, you must pass it a void pointer:
typedef void* (*fp)(void*);
doit(fp f) {
f(NULL);
}
And just make sure that the function that you're calling simply ignores the parameter.
Generally speaking, these generic function pointers are used for starting threads. The void pointer is simply a pointer to a struct that holds the actual parameters.
Upvotes: 1
Reputation: 1180
What would you need to do is wrap your function in a void function like so
#include <stdio.h>
typedef void (*fp)(void);
int sum(int x,int y) {return x+y;}
void doit(fp f) {
f();
}
void func() {
printf("Hello %d\n",sum(1,2));
}
int main() {
doit(func);
}
Upvotes: 0