GTK call member function

B

Bo Møller

The signature in the documentation is described as ( Taken from http://
library.gnome.org/devel/gobject/unstable/gobject-Closures.html#GCallback )

---------------------------------------------
void (*GCallback) (void);
---------------------------------------------
The type used for callback functions in structure definitions and function
signatures. This doesn't mean that all callback functions must take no
parameters and return void. The required signature of a callback function
is determined by the context in which is used (e.g. the signal to which it
is connected). Use G_CALLBACK() to cast the callback function to a
GCallback.
---------------------------------------------

The examples given in the tutorials have signatures like: gboolean
delete_event( GtkWidget *widget,GdkEvent *event, gpointer data) which
does not fit the signature in the docs, but a old-style cast (in the
tutorial disguised as a macro) shuts up the compiler in the tutorials!

So far I have come up with:

gulong m_destroyHandlerID;
boost::function<bool (GtkWidget*, GdkEvent*, gpointer)>
m_destroyFunctionPtr;

// SignalMember is a nonstatic member function of the Window class.
m_destroyFunctionPtr = boost::bind(&Window::SignalMember, this, _1,_2,_3);
m_destroyHandlerID = g_signal_connect_data (m_widget, "delete-event",
m_destroyFunctionPtr, NULL,NULL,0);

When compiling with gcc 4.4.1 gives an error:

error: cannot convert 'boost::function<bool(GtkWidget*, GdkEvent*,
void*)>' to 'void (*)()' for argument '3' to 'gulong
g_signal_connect_data(void*, const gchar*, void (*)(), void*, void
(*)(void*, GClosure*), GConnectFlags)'

The boost::function can't be casted to the needed type.

An obvious hack would be to replace the boost::function with
boost::function<void(void)> but I can't see how it would work when Gtk IS
passing arguments and expects a return type of bool for this particular
event.

Does anyone know how to get GTK to call a non-static member function?

Bo Møller
 
A

Alf P. Steinbach

* Bo Møller, on 14.06.2010 13:31:
The signature in the documentation is described as ( Taken from http://
library.gnome.org/devel/gobject/unstable/gobject-Closures.html#GCallback )

---------------------------------------------
void (*GCallback) (void);
---------------------------------------------
The type used for callback functions in structure definitions and function
signatures. This doesn't mean that all callback functions must take no
parameters and return void. The required signature of a callback function
is determined by the context in which is used (e.g. the signal to which it
is connected). Use G_CALLBACK() to cast the callback function to a
GCallback.
---------------------------------------------

The examples given in the tutorials have signatures like: gboolean
delete_event( GtkWidget *widget,GdkEvent *event, gpointer data) which
does not fit the signature in the docs, but a old-style cast (in the
tutorial disguised as a macro) shuts up the compiler in the tutorials!

C++ has two kinds of pointers, data pointers and function pointers. Casting from
data pointer to function pointer or vice versa is not supported (although many
compilers support, and I think Posix requires it). There is nothing like 'void*'
for function pointers, so GTK apparently used 'void(*)()' as a kind of function
pointer 'void*' pointer.


So far I have come up with:

gulong m_destroyHandlerID;
boost::function<bool (GtkWidget*, GdkEvent*, gpointer)>
m_destroyFunctionPtr;

You can't use a Boost functor (function /object/) as a function pointer.

That said, not the 'gpointer' argument at the end.

My guess is that that argument lets you pass any data to your callback. E.g., a
pointer to a C++ object. ;-)

// SignalMember is a nonstatic member function of the Window class.
m_destroyFunctionPtr = boost::bind(&Window::SignalMember, this, _1,_2,_3);
m_destroyHandlerID = g_signal_connect_data (m_widget, "delete-event",
m_destroyFunctionPtr, NULL,NULL,0);

When compiling with gcc 4.4.1 gives an error:

error: cannot convert 'boost::function<bool(GtkWidget*, GdkEvent*,
void*)>' to 'void (*)()' for argument '3' to 'gulong
g_signal_connect_data(void*, const gchar*, void (*)(), void*, void
(*)(void*, GClosure*), GConnectFlags)'

The boost::function can't be casted to the needed type.

An obvious hack would be to replace the boost::function with
boost::function<void(void)> but I can't see how it would work when Gtk IS
passing arguments and expects a return type of bool for this particular
event.

It's still a functor object, not a function pointer.

You probably need a function

extern "C" bool foo( GtkWidget* pWidget, GdkEvent* pEvent, gpointer pData )
{
return reinterpret_cast<MyClass*>( pData )->onFoo( pWidget, pEvent );
}

or something like that.

I don't know GTK.

Does anyone know how to get GTK to call a non-static member function?

See above.

If that doesn't help, use a global std::map for the association.


Cheers & hth.,

- Alf
 
T

Thomas J. Gritzan

Am 14.06.2010 13:31, schrieb Bo Møller:
The signature in the documentation is described as ( Taken from http://
library.gnome.org/devel/gobject/unstable/gobject-Closures.html#GCallback )

---------------------------------------------
void (*GCallback) (void);
---------------------------------------------
The type used for callback functions in structure definitions and function
signatures. This doesn't mean that all callback functions must take no
parameters and return void. The required signature of a callback function
is determined by the context in which is used (e.g. the signal to which it
is connected). Use G_CALLBACK() to cast the callback function to a
GCallback.
---------------------------------------------

The examples given in the tutorials have signatures like: gboolean
delete_event( GtkWidget *widget,GdkEvent *event, gpointer data) which
does not fit the signature in the docs, but a old-style cast (in the
tutorial disguised as a macro) shuts up the compiler in the tutorials!

So far I have come up with:

gulong m_destroyHandlerID;
boost::function<bool (GtkWidget*, GdkEvent*, gpointer)>
m_destroyFunctionPtr;

// SignalMember is a nonstatic member function of the Window class.
m_destroyFunctionPtr = boost::bind(&Window::SignalMember, this, _1,_2,_3);
m_destroyHandlerID = g_signal_connect_data (m_widget, "delete-event",
m_destroyFunctionPtr, NULL,NULL,0);

GTK is a C API, and boost::function is a C++ object. You can't use a C++
object as a C-style callback directly.

You either need to use a static function as trampolin function,
or you can use a C++ library, that already does that for you.

If you use C++, I would go for the C++ library. There's GTKmm, which is
a C++ API that uses GTK as low-level library.

If you want to use GTK directly, you can use a wrapper like this:
<Adapted from:
http://www.gamedev.net/community/forums/topic.asp?topic_id=487393>

#include <boost/utility.hpp>
#include <boost/function.hpp>

class signal : boost::noncopyable {
public:
typedef boost::function<bool(GtkWidget*, GdkEvent*)> function_type;

signal(GtkWidget* widget, gchar* event)
: widget(widget) {
handler = g_signal_connect(widget, event, G_CALLBACK(&f_caller),
this);
}
signal(GtkWidget* widget, gchar* event, function_type const& f)
: widget(widget), f(f) {
handler = g_signal_connect(widget, event, G_CALLBACK(&f_caller),
this);
}
signal& operator=(function_type const& f ) {
this->f = f;
return *this;
}
~signal() {
g_signal_disconnect(widget, handler);
}
private:
gulong handler;
GtkWidget* widget;
function_type f;

static bool f_caller(GtkWidget* widget, GdkEvent* event, const
signal* self)
{ return self->f(widget, event); }
};
 
P

Paul Bibbings

Bo Møller said:
The signature in the documentation is described as ( Taken from http://
library.gnome.org/devel/gobject/unstable/gobject-Closures.html#GCallback )

---------------------------------------------
void (*GCallback) (void);
---------------------------------------------
The type used for callback functions in structure definitions and function
signatures. This doesn't mean that all callback functions must take no
parameters and return void. The required signature of a callback function
is determined by the context in which is used (e.g. the signal to which it
is connected). Use G_CALLBACK() to cast the callback function to a
GCallback.
---------------------------------------------

The examples given in the tutorials have signatures like: gboolean
delete_event( GtkWidget *widget,GdkEvent *event, gpointer data) which
does not fit the signature in the docs, but a old-style cast (in the
tutorial disguised as a macro) shuts up the compiler in the tutorials!

So far I have come up with:

gulong m_destroyHandlerID;
boost::function<bool (GtkWidget*, GdkEvent*, gpointer)>
m_destroyFunctionPtr;

// SignalMember is a nonstatic member function of the Window class.
m_destroyFunctionPtr = boost::bind(&Window::SignalMember, this, _1,_2,_3);
m_destroyHandlerID = g_signal_connect_data (m_widget, "delete-event",
m_destroyFunctionPtr, NULL,NULL,0);

When compiling with gcc 4.4.1 gives an error:

error: cannot convert 'boost::function<bool(GtkWidget*, GdkEvent*,
void*)>' to 'void (*)()' for argument '3' to 'gulong
g_signal_connect_data(void*, const gchar*, void (*)(), void*, void
(*)(void*, GClosure*), GConnectFlags)'

The boost::function can't be casted to the needed type.

An obvious hack would be to replace the boost::function with
boost::function<void(void)> but I can't see how it would work when Gtk IS
passing arguments and expects a return type of bool for this particular
event.

Does anyone know how to get GTK to call a non-static member function?

You are clearly not using GTKmm, as suggested by Thomas. However, you
might be able to still get some mileage out of libsigc++, which was
written originally for the GTKmm system and much adapted since.

From their page on Sourceforge:

"libsigc++ implements a typesafe callback system for standard C++.
It allows you to define signals and to connect those signals to any
callback function, either global or member function, regardless of
whether it is static or virtual.

"It also contains adaptor classes for connection of dissimilar
callbacks..."

http://libsigc.sourceforge.net/

Regards

Paul Bibbings
 

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,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top