Il 11/05/2011 12:52, Tom St Denis ha scritto:
Oh yes, this is another solution I considered and surely it is the most
portable way.
In my case, I have a long list of const struct initialized with callback
and argument pointers, like this:
...
In your example code, you are using the same call-back for every
different number. If you are going to be using the same call-back, is
there a reason why you cannot pass a 'void *' context that points
directly to an element of an array of 'int'? As in:
---
#include <stdlib.h>
#include <stdio.h>
/*** Constants */
/* None */
/*** Object type declarations */
typedef unsigned char byte;
/*** Function types */
typedef int f_callback(const void *);
typedef int f_intfunc(int);
/*** Structure type definitions */
/* None */
/*** Function declarations */
static f_callback my_callback;
static f_intfunc some_func;
/* This one doesn't belong to you and comes from a header */
extern int SomeApiPerformCallback(f_callback *, const void *);
/*** Objects */
static int my_ints[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
/*** Function definitions */
/**
* This callback will call 'some_func' with the 'int' value
* context that is associated with it.
*/
static int my_callback(const void * context) {
const int * int_ptr;
int_ptr = context;
if (!int_ptr)
return -1;
printf("my_callback() context: %p\n", context);
return some_func(*int_ptr);
}
/**
* This quite simply returns the 'int' that is passed
*/
static int some_func(int int_param) {
printf("some_func() got: %d\n", int_param);
return int_param;
}
/**
* The program entry-point
*/
int main(void) {
int result;
result = SomeApiPerformCallback(my_callback, my_ints + 5);
if (result == -1)
return EXIT_FAILURE;
printf("Result: %d\n", result);
result = SomeApiPerformCallback(my_callback, my_ints + 7);
if (result == -1)
return EXIT_FAILURE;
printf("Result: %d\n", result);
result = SomeApiPerformCallback(my_callback, my_ints + 3);
if (result == -1)
return EXIT_FAILURE;
printf("Result: %d\n", result);
return EXIT_SUCCESS;
}
/* This one doesn't belong to you and is just a demo */
int SomeApiPerformCallback(f_callback * callback, const void * context) {
if (!callback)
return -1;
return callback(context);
}
---
I would expect that unlike this simple code, you are registering a
call-back which will be executed asynchronously relative to the function
which registers it. In that case, unless you wish to wait for the
call-back to complete, I can understand why you wouldn't want to do:
void blah(void) {
int i;
/* ... */
i = 5;
SomeApiRegisterCallback(my_callback, &i);
return;
}
because the lifetime of 'i' will end pretty well immediately after
you've registered your call-back.

But... That's what malloc() and
the other memory allocation functions are for...
void blah(void) {
int *i;
i = malloc(sizeof *i);
if (!i) {
/* Note an error */
return;
}
*i = 5;
SomeApiRegisterCallback(my_callback, i);
return;
}
Remember to free() the pointer once you've finished with it.
Any pointer type which points to a complete or incomplete object type
can be converted to 'void *' (and back again), if I recall correctly.
So that includes 'int *' -->> 'void *'.