Call Backs

E

Edward Rutherford

I've read plenty of discussion about callback functions as used in C (ie
in qsort). I'm comfortable with this: really it is a
function pointer. What I'm not sure about is how (or if) a
callback differs to events like GUI's use. One of the things I
found about events, at least in a VB6 project I did, is that an event
can be broadcast to all objects and they can use it if desired (code
only and GUI objects). Each object has to have a receive function for
that event though.

The only way I can see to do event broadcasting with a callback is to
have a special callback that in turn calls a list of receiver functions
that would be in each module. For example, a timer that broadcasts a
time tick every second would call a function (for example)
Timer_1min(void) that in turn would call functions in all of the modules
that need to know the time. I've also thought about a message que, but
that is begining to sound like too much work. Is there a better way?

Thanks for any helpful information.
 
T

tom st denis

I've read plenty of discussion about callback functions as used in C (ie
in qsort).  I'm comfortable with this: really it is a
function pointer.  What I'm not sure about is how (or if) a
callback differs to events like GUI's use.  One of the things I
found about events, at least in a VB6 project I did, is that an event
can be broadcast to all objects and they can use it if desired (code
only and GUI objects).  Each object has to have a receive function for
that event though.

The only way I can see to do event broadcasting with a callback is to
have a special callback that in turn calls a list of receiver functions
that would be in each module.  For example, a timer that broadcasts a
time tick every second would call a function (for example)
Timer_1min(void) that in turn would call functions in all of the modules
that need to know the time.  I've also thought about a message que, but
that is begining to sound like too much work.  Is there a better way?

Thanks for any helpful information.

Dude, C doesn't have "objects" ...

qsort() calls your callback [to compare items] while it's running from
your operating context. Remember C is [more or less] a single-serial
task programming language [C11 adds threading...]. So it's not like
qsort() is running in the background, and it's certainly not calling
an "object"'s callback method.
 
J

James Kuyper

On 02/15/2012 02:36 PM, tom st denis wrote:
....
Dude, C doesn't have "objects" ...

The C standard defines what an "object" is in 3.15; the concept is very
important in C. It's just not the same concept as the one you're
thinking of.
 
L

Lew Pitcher

On Wednesday 15 February 2012 14:33, in comp.lang.c,
I've read plenty of discussion about callback functions as used in C (ie
in qsort). [snip]
The only way I can see to do event broadcasting with a callback is to
[snip]

One way (doable in Standard C) would be to create /two/ functions, one to
register a callback for an event, and the other to call all callbacks on
the occurrence of the event.

Call the first function registerCallback(), and model it on the existing
atexit() or on_exit() functions, so that the caller provides the function
with the address of the function to be called when the event occurs. The
function would simply record the callback function address in a suitable,
self maintained and externally available list, and do nothing else.

Call the second function eventHappened(), and model it on the "at exit"
behaviour of the existing exit() function, in that it simply runs the list
created by the first function, calling each callback in turn.

Now, to the intended use:

Each component that wants to know about an event calls the
registerCallback() function, giving it /that component's/ function to
intercept the event.

Te component that actually initiates the event calls eventHappened(), which
calls each registered callback. Voila, a subscription-model event
broadcaster.

I've also thought about a message que, but
that is begining to sound like too much work.

And, also off topic for comp.lang.c. The use of a message queue is something
that standard C knows nothing about. It is part of the operating
environment, not the C language. (Some environments don't have message
queues).
Is there a better way?

Probably. Especially if you look to environment-specific solutions like
message queues, semaphores (standard in C11?), and other in-process
communications techniques.
 
M

Malcolm McLean

The only way I can see to do event broadcasting with a callback is to
have a special callback that in turn calls a list of receiver functions
that would be in each module.  For example, a timer that broadcasts a
time tick every second would call a function (for example)
Timer_1min(void) that in turn would call functions in all of the modules
that need to know the time.  I've also thought about a message que, but
that is begining to sound like too much work.  Is there a better way?
Bascially you do this.

You set up tick() so that it's called by the timer, maybe as an
interrupt function. You then have a global list of function pointers.
tick() calls every function pointer on the list. You have a routine to
add a fucntion pointer to the list, or to delete one.
Of course you can then add bells and whistles. You can have function
pointers that are called only once, ones that are passed data, ones
that are only called every so often.
You've got to decide how your program is going to be structured. If
you have lots of events it probably makes sense to build some sort of
message queue and to have a generic "event" structure to pass
information to standardised callback routines. If all you've got is
one timer, this is probably overkill. The main secret is to always
pass a user-supplied pointer back to the callback. That allows the
user to tag callbacks with dynamic data, and means that he can have an
arbitrary number of objects registered with the same callback routine.
 
S

Shao Miller

I've read plenty of discussion about callback functions as used in C (ie
in qsort). I'm comfortable with this: really it is a
function pointer. What I'm not sure about is how (or if) a
callback differs to events like GUI's use. One of the things I
found about events, at least in a VB6 project I did, is that an event
can be broadcast to all objects and they can use it if desired (code
only and GUI objects). Each object has to have a receive function for
that event though.

The only way I can see to do event broadcasting with a callback is to
have a special callback that in turn calls a list of receiver functions
that would be in each module. For example, a timer that broadcasts a
time tick every second would call a function (for example)
Timer_1min(void) that in turn would call functions in all of the modules
that need to know the time. I've also thought about a message que, but
that is begining to sound like too much work. Is there a better way?

You can 'typedef' a function type:

typedef int f_click(struct s_clickable *);

Then a function pointer to that type of function might be:

f_click * click;

So you might have:

struct s_clickable {
f_click * click;
};

struct s_button {
struct s_clickable clickable;
const char * caption;
};

Then, where you might have 'Sub Command1_Click' in Microsoft Visual
Basic, in C, you might do:

/* Declare using 'f_click' to ensure the type */
static f_click cmdbtn1_click;

/* Definition */
static int cmdbtn1_click(struct s_clickable * clickable) {
unsigned char * ptr;
struct s_button * button;

/*
* Non-standard 'container_of' and 'CONTAINING_RECORD'
* do something like this, but usually without the 'ptr'
* intermediary
*/
ptr = (void *) clickable;
ptr -= offsetof(struct s_button, clickable);
button = (void *) ptr;

printf("You pressed %s!\n", button->caption);
return 0;
}

struct s_button cmdbtn1 = {
/* clickable */
{ cmdbtn1_click },
/* caption */
"MyCommandButton1",
};

Then, as others have mentioned, you can have a "everything-clicked
event" and it can have a linked-list of subscribers. You can add
'&cmdbtn1.clickable' to that linked-list. The event can have an
associated function which walks the list and invokes
'list_item->clickable->click(&list_item->clickable)' for each item in
the list.

I hope this helps. :)
 
S

Shao Miller

Then, as others have mentioned, you can have a "everything-clicked
event" and it can have a linked-list of subscribers. You can add
'&cmdbtn1.clickable' to that linked-list. The event can have an
associated function which walks the list and invokes
'list_item->clickable->click(&list_item->clickable)' for each item in
the list.

Oops. I probably meant
'list_item->clickable->click(list_item->clickable)', since 'clickable'
is presumably a pointer.
 
N

Nick Keighley

On Feb 15, 2:33 pm, Edward Rutherford

not sure what "really" contributes...

probably depends on the GUI but a function pointer used as a callback
is a common way to do it. Windows commonly uses a giant switch
statement.
One of the things I
found about events, at least in a VB6 project I did, is that an event
can be broadcast to all objects and they can use it if desired (code
only and GUI objects).  Each object has to have a receive function for
that event though.
The only way I can see to do event broadcasting with a callback is to
have a special callback that in turn calls a list of receiver functions
that would be in each module.  For example, a timer that broadcasts a
time tick every second would call a function (for example)
Timer_1min(void) that in turn would call functions in all of the modules
that need to know the time.  I've also thought about a message que[ue], but
that is begining to sound like too much work.  Is there a better way?

a message queue is the common way to deal with. come on a queue isn't
that much work!

never sure what that word means or adds to the debate.
C doesn't have "objects" ...

he didn't say it did. he said VB did. C may not have objects (in your
sense) but you can implement OO GUIs in it (eg. Windows, X-Window).
qsort() calls your callback [to compare items] while it's running from
your operating context.  Remember C is [more or less] a single-serial
task programming language [C11 adds threading...].

so what?
 So it's not like
qsort() is running in the background, and it's certainly not calling
an "object"'s callback method.

that anyone suggested this is an invention of yours
 
W

Willem

Edward Rutherford wrote:
) I've read plenty of discussion about callback functions as used in C (ie
) in qsort). I'm comfortable with this: really it is a
) function pointer. What I'm not sure about is how (or if) a
) callback differs to events like GUI's use. One of the things I
) found about events, at least in a VB6 project I did, is that an event
) can be broadcast to all objects and they can use it if desired (code
) only and GUI objects). Each object has to have a receive function for
) that event though.
)
) The only way I can see to do event broadcasting with a callback is to
) have a special callback that in turn calls a list of receiver functions
) that would be in each module.

No, the place that handles the events could just have a list of callback
pointers instead of just the one, and call each one in turn. That's
usually how it's done in other languages too.

) For example, a timer that broadcasts a
) time tick every second would call a function (for example)
) Timer_1min(void) that in turn would call functions in all of the modules
) that need to know the time. I've also thought about a message que, but
) that is begining to sound like too much work. Is there a better way?

A message queue? Those are only useful in multithreaded environments, to
send information from one thread to other(s).

What are you actually trying to accomplish?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 

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
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top