Sign in to follow this  
tHiSiSbOb

passing C++ function pointers to functions within classes

Recommended Posts

Hello, I am programming something in C++ after not having touched C++ in years (I have not dropped programming, I have been using Java) and I have the following problem. I am using a library that relies on callback functions defined thusly: BOOL CALLBACK function(paramaters...){ ... } This is a sound recording app. The function that start the recording takes a function pointer to a callback function defined by me. I have a class in which a callback function is defined and the startRecord function is called. How do I pass a function pointer to that callback defined in the same class?

Share this post


Link to post
Share on other sites
From what I understand, you can't have a function pointer pointing to a non-static member function. I could be wrong though; perhaps someone with some more experience could give some better insight.

Share this post


Link to post
Share on other sites
Unless that library specifically allows for pointer to member functions, then you can't use a non-static method from a class. If it was static (or a free function), then you'd do:

setCallback(&theClass::callback); // '&' is optional with function addresses


Reason is, a free function (or static member function) address looks like this:

(returnType (*)(parameters))

But a non-static member function looks like this:

(returnType (theClass::*)(parameters))


The two are incompatible, since a member function needs an instance of the class to be called. Then you'd do:

instance.(*ptrToMemberFunction)(parameters);

Share this post


Link to post
Share on other sites
Quote:
Original post by tHiSiSbOb
Hello, I am programming something in C++ after not having touched C++ in years (I have not dropped programming, I have been using Java) and I have the following problem. I am using a library that relies on callback functions defined thusly:

BOOL CALLBACK function(paramaters...){
...
}

This is a sound recording app. The function that start the recording takes a function pointer to a callback function defined by me. I have a class in which a callback function is defined and the startRecord function is called. How do I pass a function pointer to that callback defined in the same class?


The typical way to interface with libraries requiring C-style callbacks is to register a static member function as the callback. That static member function can then dispatch a specific non-static member function to handle the callback. This is made possible by the fact that most (if not all) callback mechanisms allow you to pass a void* pointer that will be supplied to your callback function each time it is invoked. We will pass the this pointer via that argument enabling us to dispatch the appropriate member function.

To illustrate:


class Foo
{
public:

...

Foo()
{
/* Register the callback */
RegisterCallback(...,&Foo::callbackFunction, this);

}
/* Non-static member function */
void specificCallBachFunction(...)
{
...
}

/* Static member function */
static void callbackFunction(..., void* userData)
{
static_cast<Foo*>(userData)->specificCallBackFunction(...);
}
};








Share this post


Link to post
Share on other sites
Yeah, that sounds like a good idea. My problem now is that when I try to register the callback: RegisterCallback(...,&Foo::callbackFunction, this);
I get an error that tells me that I can't convert the return type of the callback function to the required type even though I know that the callback I defined is of the right type. When I use a free function, I can get around this by type-casting the free function to the type they want. When I try type casting the member function in the same way, I get another error. I am using, by the way, Visual C++ 2008 Express Edition.

The callback is defined as BOOL CALLBACK function(...,void* user);

Any ideas?

Share this post


Link to post
Share on other sites
Quote:
Original post by tHiSiSbOb
Yeah, that sounds like a good idea. My problem now is that when I try to register the callback: RegisterCallback(...,&Foo::callbackFunction, this);
I get an error that tells me that I can't convert the return type of the callback function to the required type even though I know that the callback I defined is of the right type. When I use a free function, I can get around this by type-casting the free function to the type they want. When I try type casting the member function in the same way, I get another error. I am using, by the way, Visual C++ 2008 Express Edition.

The callback is defined as BOOL CALLBACK function(...,void* user);

Any ideas?


This would be easier for us to diagnose if you posted some actual code.

Share this post


Link to post
Share on other sites
Quote:
Original post by tHiSiSbOb
Yeah, that sounds like a good idea. My problem now is that when I try to register the callback: RegisterCallback(...,&Foo::callbackFunction, this);
I get an error that tells me that I can't convert the return type of the callback function to the required type even though I know that the callback I defined is of the right type. When I use a free function, I can get around this by type-casting the free function to the type they want. When I try type casting the member function in the same way, I get another error. I am using, by the way, Visual C++ 2008 Express Edition.

The callback is defined as BOOL CALLBACK function(...,void* user);

Any ideas?


Member function pointers are of a different type. When you write


class Foo {
BOOL function(void* user);
};


, function is not, in fact, of type BOOL(*)(void*), but rather of type BOOL(Foo::*)(void*). Awful notation, I know. But there you have it.

Here's the hitch: function() is a member function of Foo objects. Suppose, for a second, that you *could* pass &Foo::function to the API. How would it know which Foo object to invoke function() on?

The reason you are given a void* parameter in C APIs is so you can pass whatever you need in there. The standard idiom to adapt C++ member functions is to pass that Foo object in there. Then, you make a wrapper:


class Foo {
BOOL function();
};

BOOL invoke_function(void* f) { (reinterpret_cast<Foo*>(f))->function(); }

Foo myFoo;
RegisterCallback(..., invoke_function, &myFoo);

Share this post


Link to post
Share on other sites
turn a nullary method into a nullary function:

typedef (void (*NullaryFn)());
struct foo { void do() {static int i=0; std::cout << ++i; };

foo instance;

boost::function<void ()> boost_fn = boost::bind(&foo::do, &instance); //see bind docs
NullaryFn cpp_fn = boost::bind(&foo::do, &instance);

instance.do(); //1
boost_fun(); //2
cpp_fn(); //3


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this