passing void function pointer

G

Guest

Hi,

I want to pass a function pointer that is a class member.

This is the fn I want to pass the function pointer into:

int Scheduler::Add(const unsigned long timeout, void* pFunction, void*
pParam)



There is another function where I make the call to the above function:

bool Scheduler::setSchedule(int interval, ComponentInterface&
CliComponent)
{
p_ClientComponent = &CliComponent;

scheduler.Add(interval, CliComponent.runAction); // here

return true;
}

As you can see the above function is passed a reference to the
ComponentInterface class

I want to use the function runAction which is part of the
ComponentInterface class as a parameter to the add function. But this
fails. This is what I need to know, how can I pass this function to the
add function.


void CliComponent::runAction()


This may be easy for some of you but its new to me, please help.
Thanks,
Enda
 
A

Alf P. Steinbach

* (e-mail address removed):
Hi,

I want to pass a function pointer that is a class member.

This is the fn I want to pass the function pointer into:

int Scheduler::Add(const unsigned long timeout, void* pFunction, void*
pParam)

'void*' is for data pointers. It's not compatible with function pointers.
The above therefore Undefined Behavior.

However, platform-specific APIs might have 'void*' function pointers.

Then you may be able to use a platform-specific reinterpret_cast.


There is another function where I make the call to the above function:

bool Scheduler::setSchedule(int interval, ComponentInterface&
CliComponent)
{
p_ClientComponent = &CliComponent;

scheduler.Add(interval, CliComponent.runAction); // here

return true;
}

As you can see the above function is passed a reference to the
ComponentInterface class

I want to use the function runAction which is part of the
ComponentInterface class as a parameter to the add function. But this
fails. This is what I need to know, how can I pass this function to the
add function.

You can not do that portably.

Non-portably: it depends on what the 'void*' pointer is assumed to be.

If it's assumed to be a straight C-style function pointer, then you need to
pass a pointer to freestanding function, that is, one that isn't a member or
if it is a member, is 'static', and it might look like this:

CliComponent* theCliComponent = 0;

void cliComponentRunAction()
{
assert( theCliComponent != 0 );
theCliComponent->runAction();
}

void* runActionCallback( CliComponent& aComponent )
{
theCliComponent = &aComponent;
return reinterpret_cast<void*>( &cliComponentRunAction );
}

and used like this:

bool Scheduler::setSchedule(
int interval, ComponentInterface& CliComponent
)
{
p_ClientComponent = &CliComponent;

scheduler.Add( interval, runActionCallback( aComponent ), 0 );
return true;
}

where you should note that in addition to being non-portable and formally UB,
it's not thread-safe, and the result type 'bool' is most probably misleading
and unnecessary (unless this function must match a specific signature).
 
G

Guest

Hi thanks for the reply,


I have decided to implement this using int pointers to the function
instead of void pointers.

int CliComponent::runAction()
{
// do something
}

Do I still need to use the function callback.

Can I do this:

bool Scheduler::setSchedule( int interval, ComponentInterface&
CliComponent)
{
p_ClientComponent = &CliComponent;

scheduler.AddTask(interval, p_ClientComponent->runAction, 0);
return true;
}

int Scheduler::Add(const unsigned long timeout, int* pFunction, void*
pParam)

This of course does not work.

Thanks again
 
?

=?iso-8859-1?Q?Ali_=C7ehreli?=

I have decided to implement this using int pointers to the function
instead of void pointers.

int pointers are to point to ints. They can't point to functions.
int CliComponent::runAction()
{
// do something
}

Do I still need to use the function callback.

Can I do this:

bool Scheduler::setSchedule( int interval, ComponentInterface&
CliComponent)
{
p_ClientComponent = &CliComponent;

scheduler.AddTask(interval, p_ClientComponent->runAction, 0);
return true;
}

I don't understand your question clearly. In your original post, you called
runAction "a part of the ComponentInterface class." Does that mean that
there is a function pointer member in each object?

If so, here is an example for the function pointer that is a public member:

#include <iostream>

int twice(int number)
{
return number * 2;
}

typedef int (*Function)(int);

class Foo
{
public:

// Public data member is not good!
Function function_;

explicit Foo(Function function)
:
function_(function)
{}
};

// This function receives a reference to an object and calls a function,
// which is "a part of" that object.

void user(Foo const & foo)
{
std::cout << (foo.function_)(2) << '\n';
}

int main()
{
Foo foo(twice);
user(foo);
}

When you said "a part of the ComponentInterface class," if you actually
meant "a part of the class," then may be you are talking about member
function pointers. Here is an example:

#include <iostream>

class Foo
{
public:

int twice (int number) { return number * 2; }
int thrice(int number) { return number * 3; }
};

typedef int (Foo::*MemberFunction)(int);

void user(Foo & foo, MemberFunction function)
{
std::cout << (foo.*function)(2) << '\n';
}

int main()
{
Foo foo;
user(foo, &Foo::twice);
user(foo, &Foo::thrice);
}

Ali
 
G

Greg

Hi thanks for the reply,


I have decided to implement this using int pointers to the function
instead of void pointers.

int CliComponent::runAction()
{
// do something
}

Do I still need to use the function callback.

Can I do this:

bool Scheduler::setSchedule( int interval, ComponentInterface&
CliComponent)
{
p_ClientComponent = &CliComponent;

scheduler.AddTask(interval, p_ClientComponent->runAction, 0);
return true;
}

int Scheduler::Add(const unsigned long timeout, int* pFunction, void*
pParam)

This of course does not work.

Thanks again

The question is how to specify a member function pointer as a callback
routine. The problem with passing a member function pointer such
&ComponentInterface::runAction is that the function accepting the
callback needs to expect a member function pointer for that particular
class, in this case, ComponentInterface:

int Scheduler::Add( const unsigned long timeout,
int (ComponentInterface::*)())

Since the Add() method has to know the member function's class, then
there is little reason for it not to know which member function in that
class it should be calling. So why bother with the callback at all? Why
not just pass a ComponentInterface pointer? In other words, because a
member function pointer is class-specific, it is not suitable for use
as a generic callback routine.

There is a solution however. Most callbacks consist of a function
pointer and a "user data" pointer that is passed to the function when
it is called. This data pointer allows the callback routine to
"recover" an object and then call its appropriate method. Such an
approach would look something like this:

The function accepting the callback also accepts a user data pointer:

int Scheduler::Add( const unsigned long timeout,
int (*inCallback)(void *),
void *inUserData)


The client specifies the callback like so:

{
ComponentInterface theComp;

scheduler->Add(0, MyCallBack, &theComp);


and the callback routine itself:

int MyCallBack( void *inMyData)
{
ComponentInterface * component;

component = static_cast<ComponentInterface*>(inMyData);
component->runAction();
}

This technique is not ideal since type information is lost and then
recovered. But it does help to prevent unnecessary dependencies
between the callback and the caller.

Greg
 
B

Bob Hairgrove

int MyCallBack( void *inMyData)
{
ComponentInterface * component;

component = static_cast<ComponentInterface*>(inMyData);
component->runAction();
}

reinterpret_cast is what you want.
 
G

Greg

Bob said:
reinterpret_cast is what you want.

A static_cast is fine. A program can always safely convert a object
pointer to a void pointer and back again.

In reality, it makes no difference. Neither a static_cast or
reinterpret_cast generate any machine instructions. They are both
no-ops used to placate the compiler's type checking. Therefore when
choosing between them, one should favor a static_cast if possible. A
static cast communicates that the cast has reasonable assurance of
being safe. Since the void * conversion is a supported conversion, a
static_cast is the one to use.

Of course, if the void * is pointing to a different class of object
than the one expected, the program is in trouble. Using a
reinterpret_cast instead of static_cast would of course not have
changed that fact, and in fact would not have changed anything at all.

Greg
 

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,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top