c++-gtk-utils
|
Any function connecting to a GObject signal, such as any GTK+ signal, must have C linkage. In C++, function pointers have a linkage specification (C or C++) in the same way that functions do, and although name mangling would not be an issue with respect to function pointers, the calling convention is. Thus, functions with C linkage specification have arguments passed on the stack, whereas functions with C++ linkage specification can optimise by passing arguments in registers or by manipulating the stack frame 'in situ'. Different calling conventions also vary in the way they allocate responsibility, as between caller and called, for resetting stack pointers when a function call exits. With some compilers such as gcc, static class member functions adopt the C calling convention and so can be passed as GObject callbacks, but this is not required by the standard and some compilers (for example, some of the Intel compilers) do not.
This means that functions to be passed as GObject callbacks should be declared as having C language linkage (that is, be declared 'extern "C"'). The WinBase example does this with respect to the message_button_clicked() callback. In that example, this function has to be declared in the header file so that it can be made a friend of the class and so call the protected function Cgu::WinBase::close(). This means it will appear in the global namespace. Putting it within a C++ namespace is of limited effect as at link time C++ namespaces are ignored in the case of functions with C linkage. (So far as linkage is concerned, it could be given internal linkage by declaring it static, but that would cause any other translation unit incorporating the header file to issue an albeit harmless warning about a static function being declared without a definition.)
Where a particular class implementation uses a number of GObject signal callbacks, it can be inconvenient to have several callback functions in global scope, and pollutes the global namespace. One useful technique to avoid this is the friend helper class, which can also be a nested class. Take a class Dialog derived from Cgu::WinBase which connects to two GTK+ signals, say "clicked" and "expose-event", for which both callbacks need to access private or protected data or methods of the class. Complete hiding can be achieved in this way:
Because the static member functions of Dialog::CB in this example are implicitly inline, there should be no efficiency implications.
Another approach is to use Callback::CallbackArg objects with g_signal_connect_data():
This approach can be particularly useful where other data which is not a class member is to be bound to the callback object at connect time, such as a button number. (That is not the case in these examples.)