C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

passing void function pointer

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
keepyourstupidspam@yahoo.
Guest





PostPosted: Thu Sep 29, 2005 1:14 pm    Post subject: passing void function pointer Reply with quote



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

Back to top
Alf P. Steinbach
Guest





PostPosted: Thu Sep 29, 2005 1:28 pm    Post subject: Re: passing void function pointer Reply with quote



* [email]keepyourstupidspam (AT) yahoo (DOT) co.uk[/email]:
Quote:
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.



Quote:
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).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Back to top
keepyourstupidspam@yahoo.
Guest





PostPosted: Thu Sep 29, 2005 3:10 pm    Post subject: Re: passing void function pointer Reply with quote



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

Back to top
Ali Çehreli
Guest





PostPosted: Thu Sep 29, 2005 7:29 pm    Post subject: Re: passing void function pointer Reply with quote

<keepyourstupidspam (AT) yahoo (DOT) co.uk> wrote


Quote:
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.

Quote:
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
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


Back to top
Greg
Guest





PostPosted: Thu Sep 29, 2005 10:27 pm    Post subject: Re: passing void function pointer Reply with quote

[email]keepyourstupidspam (AT) yahoo (DOT) co.uk[/email] wrote:
Quote:
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


Back to top
Bob Hairgrove
Guest





PostPosted: Fri Sep 30, 2005 10:33 am    Post subject: Re: passing void function pointer Reply with quote

On 29 Sep 2005 15:27:14 -0700, "Greg" <greghe (AT) pacbell (DOT) net> wrote:

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

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

reinterpret_cast is what you want.

--
Bob Hairgrove
[email]NoSpamPlease (AT) Home (DOT) com[/email]

Back to top
Greg
Guest





PostPosted: Fri Sep 30, 2005 11:13 am    Post subject: Re: passing void function pointer Reply with quote

Bob Hairgrove wrote:
Quote:
On 29 Sep 2005 15:27:14 -0700, "Greg" <greghe (AT) pacbell (DOT) net> wrote:

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

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

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


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.