473,385 Members | 1,535 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

passing void function pointer

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

Sep 29 '05 #1
6 8800
* ke****************@yahoo.co.uk:
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).

--
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?
Sep 29 '05 #2
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

Sep 29 '05 #3
<ke****************@yahoo.co.uk> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...
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

Sep 29 '05 #4
ke****************@yahoo.co.uk wrote:
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

Sep 29 '05 #5
On 29 Sep 2005 15:27:14 -0700, "Greg" <gr****@pacbell.net> wrote:
int MyCallBack( void *inMyData)
{
ComponentInterface * component;

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


reinterpret_cast is what you want.

--
Bob Hairgrove
No**********@Home.com
Sep 30 '05 #6
Bob Hairgrove wrote:
On 29 Sep 2005 15:27:14 -0700, "Greg" <gr****@pacbell.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

Sep 30 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of...
6
by: bob_jenkins | last post by:
{ const void *p; (void)memset((void *)p, ' ', (size_t)10); } Should this call to memset() be legal? Memset is of type void *memset(void *, unsigned char, size_t) Also, (void *) is the...
9
by: Juggernaut | last post by:
I am trying to create a p_thread pthread_create(&threads, &attr, Teste, (void *)var); where var is a char variable. But this doesnt't work, I get this message: test.c:58: warning: cast to pointer...
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
17
by: Charles Sullivan | last post by:
The library function 'qsort' is declared thus: void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); If in my code I write: int cmp_fcn(...); int...
1
by: Shawn | last post by:
As if it won't be clear enough from my code, I'm pretty new to C programming. This code is being compiled with an ANSI-C compatible compiler for a microcontroller. That part, I believe, will be...
12
by: Mike | last post by:
Consider the following code: """ struct person { char *name; int age; }; typedef struct person* StructType;
3
by: dice | last post by:
Hi, In order to use an external api call that requires a function pointer I am currently creating static wrappers to call my objects functions. I want to re-jig this so I only need 1 static...
2
by: sonaliagr | last post by:
I am trying to update a msg array in function by passing the address but it is showing an error. and also, i want the value of msg array to be accessible to the full code that is inside the main...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.