registering class methods as C style callbacks

N

noone

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
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

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.
 
N

noone

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.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

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.
 
H

Howard Gardner

// 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 >::eek:bj;

int
main()
{
typedef bound_func< demo, &demo::func > tBound;
tBound::call();
// &tBound::call should be suitable for a callback
}
 
J

Jon Clements

Julián Albo said:
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.

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.
 
V

Victor Bazarov

Jon said:
[..]
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
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Jon said:
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.
 
J

Jon Clements

Victor said:
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.
 
H

Howard Gardner

Jon said:
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().
 
J

Jon Clements

Julián Albo said:
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
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
 
N

noone

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.
 
V

Victor Bazarov

noone said:
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
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top