By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,148 Members | 759 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,148 IT Pros & Developers. It's quick & easy.

registering class methods as C style callbacks

P: n/a
consider the following problem:

You have a C style library and API that uses callbacks to implement
functionality. Examples of this are X11 API, OpenGL/GLUT...The List goes
on.

The power of virtuals in C++ leads us to want to implement a framework
where those callbacks are simply overriden virtual methods in a derived
class. So...

struct A {
A() { ::set_timerroutine(timerroutine); }
~A() { ::clear_timerroutine(); }
void timerroutine() { action(); }
virtual void action()=0;
};

struct B: public A {
B(): A() {}
action() { // do something relevant here }
};

B myTimerObject;
On the surface we would expect that registering the class method
timerroutine in the constructor for A would cause B::action() to be
invoked but I've not found a way to cast a class method to a generic
function pointer as is expected in C style callbacks.

How can I accomplish this without the extremely ugly overhead of
"referencing static object pointers in a C style timerroutine() that is
not itself a class method?"

The idea/requirement is to have a framework that can exist solely in a
header file and thus serve as a template.

-Rob
Jul 17 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
no***@all.com wrote:
On the surface we would expect that registering the class method
timerroutine in the constructor for A would cause B::action() to be
invoked but I've not found a way to cast a class method to a generic
function pointer as is expected in C style callbacks.
A cast is not enough. To use a member function you need both the function
and an object.

Systems with callbacks usually provide a way to pass a pointer to the
function that sets the callback, and pass this pointer value when calling
the callback function. You just need to use a pointer to a base class, and
use it to call the virtual function you want.

--
Salu2
Jul 17 '06 #2

P: n/a
On Mon, 17 Jul 2006 21:22:00 +0200, Julián Albo wrote:
no***@all.com wrote:
>On the surface we would expect that registering the class method
timerroutine in the constructor for A would cause B::action() to be
invoked but I've not found a way to cast a class method to a generic
function pointer as is expected in C style callbacks.

A cast is not enough. To use a member function you need both the function
and an object.

Systems with callbacks usually provide a way to pass a pointer to the
function that sets the callback, and pass this pointer value when calling
the callback function. You just need to use a pointer to a base class, and
use it to call the virtual function you want.
Either I'm not understanding your explanation or you don't understand my
problem fully: maybe a bit of both. registering a callback simply uses a
function pointer (ptr*)() and since class methods are not really function
pointers they cannot be directly registered in APIs that use C style
callbacks. I need a way of registering them that does NOT require static
pointers, or global C functions to get around the function pointer
problem. this solution MUST be fully implementable in a header file so
that it can serve as a template.
Jul 17 '06 #3

P: n/a
no***@all.com wrote:
Either I'm not understanding your explanation or you don't understand my
problem fully: maybe a bit of both. registering a callback simply uses a
function pointer (ptr*)() and since class methods are not really function
pointers they cannot be directly registered in APIs that use C style
callbacks. I need a way of registering them that does NOT require static
pointers, or global C functions to get around the function pointer
problem. this solution MUST be fully implementable in a header file so
that it can serve as a template.
The fact that you want it does not make it possible. If you want to use a
non static member function you need a way to provide an object. If the
callback style does not allow it, you need to use a global variable or some
other workaround.

--
Salu2
Jul 17 '06 #4

P: n/a
// This should see you on your way.

#include <cstddef>
#include <ostream>
using namespace std;

struct demo
{
void
func()
{
cout << "called" << endl;
}
};

template< typename xObj, void (xObj::*xPtr)() >
struct
bound_func
{
static
xObj
obj;

static
void
call()
{
(obj.*xPtr)();
}
};

template< typename xObj, void (xObj::*xPtr)() >
xObj
bound_func< xObj, xPtr >::obj;

int
main()
{
typedef bound_func< demo, &demo::func tBound;
tBound::call();
// &tBound::call should be suitable for a callback
}
Jul 17 '06 #5

P: n/a

Julián Albo wrote:
no***@all.com wrote:
Either I'm not understanding your explanation or you don't understand my
problem fully: maybe a bit of both. registering a callback simply uses a
function pointer (ptr*)() and since class methods are not really function
pointers they cannot be directly registered in APIs that use C style
callbacks. I need a way of registering them that does NOT require static
pointers, or global C functions to get around the function pointer
problem. this solution MUST be fully implementable in a header file so
that it can serve as a template.

The fact that you want it does not make it possible. If you want to use a
non static member function you need a way to provide an object. If the
callback style does not allow it, you need to use a global variable or some
other workaround.

--
Salu2
My C++ is a little rusty (and I don't have a compiler handy to try) -
so ignore me if I'm talking dribble. Is it possible that mem_fun_ref
can be used to create a unary function object, which is then passed to
the callback? But like I say, not sure that would work, or indeed, if
it's safe. However, could throw a possible angle on things (or not...)
Jon.

Jul 17 '06 #6

P: n/a
Jon Clements wrote:
[..]
My C++ is a little rusty (and I don't have a compiler handy to try) -
so ignore me if I'm talking dribble. Is it possible that mem_fun_ref
can be used to create a unary function object, which is then passed to
the callback? But like I say, not sure that would work, or indeed, if
it's safe. However, could throw a possible angle on things (or not...)
Any templates from C++ Standard Library (and objects derived therefrom)
are useless when C callbacks are concerned). C has no idea about any
"function objects".

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 17 '06 #7

P: n/a
Jon Clements wrote:
My C++ is a little rusty (and I don't have a compiler handy to try) -
so ignore me if I'm talking dribble. Is it possible that mem_fun_ref
can be used to create a unary function object, which is then passed to
the callback? But like I say, not sure that would work, or indeed, if
it's safe. However, could throw a possible angle on things (or not...)
mem_fun_ref has no magic, it just creates objects that pass references to
the object you pass and the member function you want to use. The problem is
the same as if you write a specific class for the task.

What specific problem are you trying to solve? Maybe there are other ways to
do the task.

--
Salu2
Jul 17 '06 #8

P: n/a

Victor Bazarov wrote:
Any templates from C++ Standard Library (and objects derived therefrom)
are useless when C callbacks are concerned). C has no idea about any
"function objects".
Surely though - if it just dereferences the function object (or pointer
to it maybe?), it doesn't even need to know it's a function object?

Jon.

Jul 17 '06 #9

P: n/a

Julián Albo wrote:
mem_fun_ref has no magic, it just creates objects that pass references to
the object you pass and the member function you want to use. The problem is
the same as if you write a specific class for the task.

What specific problem are you trying to solve? Maybe there are other waysto
do the task.
Was just wondering if it was a possible solution for the OP. However, I
think Victor and yourself have enlightened me to the fact, this
wouldn't be a solution.

Just seemed to make sense at the time of generating a function object
and passing the address of that to the callback....

Cheers

Jon

Jul 17 '06 #10

P: n/a
Jon Clements wrote:
Victor Bazarov wrote:
>Any templates from C++ Standard Library (and objects derived therefrom)
are useless when C callbacks are concerned). C has no idea about any
"function objects".

Surely though - if it just dereferences the function object (or pointer
to it maybe?), it doesn't even need to know it's a function object?

Jon.
It also passes a pointer to the object to the function (its the "this"
pointer). That's the problem.

a.func() is kindof the same as func(&a), not func().
Jul 17 '06 #11

P: n/a
Jon Clements wrote:
>mem_fun_ref has no magic, it just creates objects that pass references to
the object you pass and the member function you want to use. The problem
is the same as if you write a specific class for the task.

What specific problem are you trying to solve? Maybe there are other ways
to do the task.

Was just wondering if it was a possible solution for the OP. However, I
Sorry, 'you' intended to be 'the OP'

--
Salu2
Jul 17 '06 #12

P: n/a
On Mon, 17 Jul 2006 20:02:47 +0000, Howard Gardner wrote:
template< typename xObj, void (xObj::*xPtr)() >
struct
bound_func
{
static
xObj
obj;

static
void
call()
{
(obj.*xPtr)();
}
};

thanks, but wouldn't

static xObj obj

also need to be defined in a source file as well as being declared in the
template header as you show above? the requirement of a definition in a
related source file is what I'm trying to get away from.
Jul 22 '06 #13

P: n/a
noone wrote:
On Mon, 17 Jul 2006 20:02:47 +0000, Howard Gardner wrote:
>template< typename xObj, void (xObj::*xPtr)() >
struct
bound_func
{
static
xObj
obj;

static
void
call()
{
(obj.*xPtr)();
}
};


thanks, but wouldn't

static xObj obj

also need to be defined in a source file as well as being declared in
the template header as you show above? the requirement of a
definition in a related source file is what I'm trying to get away
from.
Since it's a member of a class template, it's a template itself. You
don't need to define it in a source file, but you need to define it
outside the class template, in the same header. When you use it, the
static data member will be first *instantiated* and then *initialised*
according to your "definition" statement. You needn't worry about
putting it in a source file somewhere.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 24 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.