need addititional arg in given callback

R

Richard Bos

Felix Kater said:
in a given library I register callback functions with this function:

bool set_callback(int index, int (*callback_function)(long));

I need the callback function to also pass the index which is, however,
not (re-)passed by the callback function.

Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at design
time... But it isn't.

Could someone help me find the right approach to solve that problem?

It's a quandary. You'd like closures for something like this, but you
don't have those in C. A quick and dirty hack would be to use a
file-scope (i.e., global, or if at all possible, file-local) variable,
possibly with the aid of a helper function if you can't change the
callback function itself.

Richard
 
F

Felix Kater

Hi,

in a given library I register callback functions with this function:

bool set_callback(int index, int (*callback_function)(long));

I need the callback function to also pass the index which is, however,
not (re-)passed by the callback function.

Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at design
time... But it isn't.

Could someone help me find the right approach to solve that problem?

Felix
 
K

Keith Thompson

Felix Kater said:
in a given library I register callback functions with this function:

bool set_callback(int index, int (*callback_function)(long));

I need the callback function to also pass the index which is, however,
not (re-)passed by the callback function.

Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at design
time... But it isn't.

If you can't change the type of the argument passed to the callback
function, you could make its argument an index into a data structure
from which it can retrieve as much information as you care to provide.

The simplest such data structure, of course, is an array (presumably
of structs or of pointers to structs). If you don't know in advance
how many elements you'll need, allocate it dynamically and use
realloc() as needed to expand it.
 
F

Felix Kater

A quick and dirty hack would be to use a
file-scope (i.e., global, or if at all possible, file-local) variable,
possibly with the aid of a helper function

Good to hear that there's a way, however, could you elaborate that a
bit to me?

Felix
 
F

Felix Kater

Keith Thompson said:
If you can't change the type of the argument passed to the callback
function, you could make its argument an index into a data structure

I'm afraid I didn't get the point:

a. I can't re-use the long arg from the callback function as a pointer
since this value (which is passed) has nothing to do with the index
value I need inside the callback function and which I pass to the
register function.

b. If you ment to make an array of function pointers: How would I fill
that with meaningfull pointers to functions which I would have to hard
code anyway?

Felix
 
K

Keith Thompson

Felix Kater said:
I'm afraid I didn't get the point:

a. I can't re-use the long arg from the callback function as a pointer
since this value (which is passed) has nothing to do with the index
value I need inside the callback function and which I pass to the
register function.
[snip]

Sorry, I think I misunderstood the problem (I don't often use callback
functions). I was thinking you could control the long value passed to
the callback function, but obviously it's called by the library in a
manner you can't control.

The library provides:

bool set_callback(int index, int (*callback_function)(long));

What does the long argument represent?

(There may not be a good way to do what you want.)
 
C

CBFalconer

Felix said:
in a given library I register callback functions with this
function:

bool set_callback(int index, int (*callback_function)(long));

I need the callback function to also pass the index which is,
however, not (re-)passed by the callback function.

Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at
design time... But it isn't.

Could someone help me find the right approach to solve that
problem?

This has nothing to do with the portable standard C language, but
deals with your particular system and installation. So find a
newsgroup that deals with that system.
 
K

Keith Thompson

CBFalconer said:
This has nothing to do with the portable standard C language, but
deals with your particular system and installation. So find a
newsgroup that deals with that system.

I don't agree that the question is necessarily off-topic. He's using
a particular system-specific library, and details about the workings
of that library would certainly be off-topic, but there have already
been several responses about possible solutions that depend only on
the set_callback declaration he's shown us.

It may turn out that the *solution* is either system-specific (and
therefore off-topic) or nonexistent.
 
F

Felix Kater

Keith Thompson said:
It may turn out that the *solution* is either system-specific (and
therefore off-topic) or nonexistent.

The more I ask people about that problem the more I believe there is no
clean solution: Since the only distinguishing information between the
callback functions the client programmer gets are the function pointers
itself I can only register different functions -- and, as I don't know
how many there will be necessary I don't see any way to do that in advance.

Felix
 
E

E. Robert Tisdale

Felix said:
in a given library I register callback functions with this function:

bool set_callback(int index, int (*callback_function)(long));

Did you write this function?
What is the index argument used for?
I need the callback function to also pass the index
which is, however, not (re-)passed by the callback function.

What do you mean here?
Your *set_callback* function passes index
but your *callback* function does not?
Normally, I would just register callback functions
for each index [that] I need
if the [number] of callback functions was known at design time...
But it isn't.

Could someone help me find the right approach to solve that problem?

What problem?
Try to elaborate a little more.
Show us an example.
 
R

Richard Bos

Felix Kater said:
Good to hear that there's a way, however, could you elaborate that a
bit to me?

AFAICT, what you want is something like this:

int callback(long index)
{
return some_lookup[index];
}

which you can set up with

set_callback(&callback, some_index);

and should then be called by the surrounding code (probably a library or
the OS API) like this:

callback(index);

whereas what this code actually does is this:

callback();

and you're required to set things up using

set_callback(&callback);

with no provision for passing in the required index.

Is that impression of what you want right? If not, I'm sorry, I
misunderstood what you want. If it is, though, you could do this
instead:

long public_index;

int callback_helper(void)
{
return callback(public_index);
}

public_index=some_index;
set_callback(&callback_helper);

so that a call to the callback function will result in

callback_helper();

which will fetch the index you wanted, and then call the original
callback function with that value.

Richard
 
F

Felix Kater

E. Robert Tisdale said:
Did you write this function?

No, and I can't change it.

What is the index argument used for?

It's used for the logic inside the library. Think of a simple
assignment which hardware event is bound to what callback.
If this index was passed to/by the callback as an argument I would be
done...

What do you mean here?
Your *set_callback* function passes index
but your *callback* function does not?

Exactly. If the callback would pass the index I could just use one
callback function for all indexes and check the index what to do.
Without that I have to create callback functions for each index. That's
the problem...

More and more I think there is no general way out of this dilemma. I'll
try to contact the distributor of the libraray and ask if they could
pass the index argument with the next release.

Felix
 
F

Felix Kater

Is that impression of what you want right? If not, I'm sorry, I
misunderstood what you want. If it is, though, you could do this
instead:

long public_index;

int callback_helper(void)
{
return callback(public_index);
}

public_index=some_index;
set_callback(&callback_helper);

so that a call to the callback function will result in

callback_helper();

which will fetch the index you wanted, and then call the original
callback function with that value.


Thanks for that, Richard.
You didn't misunderstand me.

I realize now, however, that I didn't mention the fact clearly that I
have to register more than one callback function in the beginning
(rather than set and unset them) which will then be called at any time
in any order. So, I don't know when to set the public_index.

Felix
 
R

Richard Bos

Felix Kater said:
Thanks for that, Richard.
You didn't misunderstand me.

I realize now, however, that I didn't mention the fact clearly that I
have to register more than one callback function in the beginning
(rather than set and unset them) which will then be called at any time
in any order. So, I don't know when to set the public_index.

O-kay... so in effect, you cannot even do this:

public_index=index1;
function_which_will_call_your_callback();

... more code...

public_index=index2;
function_which_will_call_your_callback();

and so forth, because the function will need to be called
asynchronously, behind your back? In that case, I'm afraid I don't know
a solution, either.

Richard
 
P

Peter Nilsson

Felix said:
in a given library I register callback functions with this function:

bool set_callback(int index, int (*callback_function)(long));

I need the callback function to also pass the index which is, however,
not (re-)passed by the callback function.

Why do you _need_ the index?
Normally, I would just register callback functions for each
index I need if the amount of callback functions was known at
design time... But it isn't.

Could someone help me find the right approach to solve that problem?

The right approach is make your callback functions independant of
the index, or to persuade the library writers to redesign their
callback interface.

A kludge though is something like the code below. You make your
callback functions take the int parameter (A, B and C below),
and put a wrapper around the the set_callback function...

#include <stdio.h>
#include <stdlib.h>

typedef int wrapper_f(long);
typedef int callback_f(int, long);

#define countof(x) (sizeof(x) / sizeof *(x))

#define blank
#define semicolon ;
#define comma ,

/* specify the indexes to wrap with this macro */
#define the_indexes(M,_) \
M( 1) _ \
M( 2) _ \
M( 7) _ \
M(12) _ \
M(42)

struct wt_element_t
{
const int index;
wrapper_f * const wrapper;
callback_f *callback;
};

struct wt_element_t wrapper_table[];

#define as_enums(I) wrapper_ ## I ## _e
#define as_initialisors(I) { I, wrapper_ ## I, 0 }

#define as_function_declarations(I) \
int wrapper_ ## I (long)

#define as_function_definitions(I) \
int wrapper_ ## I (long n) \
{ \
return wrapper_table[wrapper_ ## I ## _e]. \
callback(I, n); \
}

enum my_wrapper_enums { the_indexes(as_enums, comma) };
the_indexes(as_function_declarations, semicolon);

/* put these in a single source file */

the_indexes(as_function_definitions, blank)

struct wt_element_t wrapper_table[] =
{ the_indexes(as_initialisors, comma) };

int set_callback_wrapper(int index, callback_f *callback)
{
size_t i;
for (i = 0; i < countof(wrapper_table); i++)
if (wrapper_table.index == index)
{
wrapper_table.callback = callback;
/* install the wrapper callback function */
/* set_callback(index, wrapper_table.wrapper); */
return 1;
}
return 0;
}

/* sample usage */

/* your callback functions */
int A(int i, long n) { return printf("A(%2d, %3ld)\n", i, n); }
int B(int i, long n) { return printf("B(%2d, %3ld)\n", i, n); }
int C(int i, long n) { return printf("C(%2d, %3ld)\n", i, n); }

int main(void)
{
long n;

/* install callbacks */
set_callback_wrapper( 1, A);
set_callback_wrapper( 2, B);
set_callback_wrapper(12, C);
set_callback_wrapper(42, A);

/* simulate 20 pseudo random callbacks */
for (n = 1; n <= 20; n++)
{
size_t i = rand() % countof(wrapper_table);
while (wrapper_table.callback == 0)
i = (i + 1) % countof(wrapper_table);
wrapper_table.wrapper(n);
}

return 0;
}
 
F

Felix Kater

because the function will need to be called
asynchronously, behind your back? In that case, I'm afraid I don't know
a solution, either.

Unfortunatelly, yes. Thanks again.

Felix
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,901
Members
47,439
Latest member
elif2sghost

Latest Threads

Top