Presentation is loading. Please wait.

Presentation is loading. Please wait.

N ATIONAL E NERGY R ESEARCH S CIENTIFIC C OMPUTING C ENTER Charles Leggett Callbacks May 2 2003.

Similar presentations


Presentation on theme: "N ATIONAL E NERGY R ESEARCH S CIENTIFIC C OMPUTING C ENTER Charles Leggett Callbacks May 2 2003."— Presentation transcript:

1 N ATIONAL E NERGY R ESEARCH S CIENTIFIC C OMPUTING C ENTER Charles Leggett Callbacks May 2 2003

2 2 Charles Leggett Callbacks â In C, callbacks are easy - one can store the address of a callback function in a variable. â In C++, it’s trickier - while one can get the address of global functions, static objects, and static member functions of objects, it’s more difficult to extract the actual address of a non-static member function of a non-static object. â Most generalized callback frameworks in C++ make use of inheritance to define an access point to an object’s member functions.

3 3 Charles Leggett libsigc++ â C++ library (not just header files) â Can handle: l member function of any object derived from SigC::Object l function object derived from SigC::Object l static, global or friend function l static function object l member function to a static object â three separate entities involved in mechanism: l sender l receiver l someone making connection between the two

4 4 Charles Leggett libsigc++ â sender specifies an interface which it can call when it wants to tell other objects something. This interface is specified as a function object and is called "Signal". Calling that interface is called "emitting a signal". â All connections share a common syntax through a factory that creates an abstract function object called a "Slot.” l signal.connect(slot(object,Object::&method)); l signal.connect(slot(&function)); l signal.connect(functionobject.slot()) â Making a connection connects sender to the receiver. After that, if the sender emits a signal, all methods, functions and function objects that have been connected to that signal are called with the arguments given at signal emission. â Signature of both sender interface and receiver method must match exactly to be able to make connection between them. If there's type mismatches in the signatures, C++ compiler will give compile time type error.

5 5 Charles Leggett Signal Implementation â Signals are C++ function objects: â A connection from a signal to a (member) function matching signal's interface can be made: â If the function is a member function â Calling a signal looks exactly like calling a normal C++ function: signal buttonPressed; void my_function(int param1, float param2); buttonPressed.connect(slot(&my_function)); MyClass myobject; buttonPressed.connect(slot(myobject,&MyClass::my_function)); buttonPressed(10, 20.0);

6 6 Charles Leggett Mismatched argument types and counts â Can also connect functions to signals with different arguments or return types using adapters by generating new slot objects that wrap around an existing slot: { slot1 bind (slot2 &, T2 &extra); slot2 hide (slot1 &); slot2 retype (slot1 &); }

7 7 Charles Leggett Handling Return Values â What is the return value of a Signal that in turn calls many different callbacks that each return a different value? â library offers a Marshal object, taken as an extra template argument to a signal, that allows processing of return codes. â The marshalling function will be called with the return value of each slot connected to the signal as they are called. The emission process can be stopped by the marshalling function returning true.

8 8 Charles Leggett Callbacks Without Inheritance â What if you need to perform a callback to a member function of a class that isn’t static, and doesn’t inherit from a base class? â The problem is that there is no way in C++ to identify the exact address of a member function. â Seems weird doesn’t it? The compiler knows the address - it has to be able to call it, but there is no way to display this value. â Or is there? â We can use bind(), to bind a member function declaration to an instantiated object, and then call it, but we need a way of uniquely identifying each such bound function.

9 9 Charles Leggett Binding Functions â It’s easier to use the boost::bind() function than the stl bind, but it essentially does the same thing: class CBK { public: float fcn(int _i) { return _i/3.; } }; { CBK cb1; boost::function bfcn (boost::bind(&CBK::fcn, &cb1, _1)); cout 3.0

10 10 Charles Leggett Binding Functions â But once it’s bound to a boost::function, there’s no way to identify the objects that went into it. â We need to find a way to uniquely identify an function/object pair, and associate it with the boost::function. â Easy to identify the object - just use the address. â But what about the function? Can’t print out “&CBK::fcn” - it’s not static: { cout << &CBK::fcn << endl; } output> 1

11 11 Charles Leggett Function Addresses â Turns out, that printf is much smarter than cout: â This is actually dependent on the compiler used. gcc 2.95 can’t distinguish between the non-virtual functions, but gcc 3.2 can class CBK { public: float fcn1(int) {}; float fcn2(int) {}; virtual float fcn3(int) {}; virtual float fcn4(int) {}; }; { printf (“%x %x %x %x\n”, &CBK::fcn1, &CBK::fcn2 &CBK::fcn3, &CBK::fcn4); } output> 1 5 8049234 8049254

12 12 Charles Leggett Putting it all together â Now we can uniquely identify any member function, using the address of the object, and the address of the function returned by sprintf. We can then associate this information with the address of the boost::function, and individually call any function at will, without having to resort to inheritance or static functions.


Download ppt "N ATIONAL E NERGY R ESEARCH S CIENTIFIC C OMPUTING C ENTER Charles Leggett Callbacks May 2 2003."

Similar presentations


Ads by Google