passing C++ function pointers to functions within classes

Started by
6 comments, last by thedustbustr 15 years, 9 months ago
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?
----------------------------------------------------"Plant a tree. Remove a Bush" -A bumper sticker I saw.
Advertisement
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.
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);
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(...);    }};
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?

----------------------------------------------------"Plant a tree. Remove a Bush" -A bumper sticker I saw.
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.
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);
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 docsNullaryFn cpp_fn = boost::bind(&foo::do, &instance);instance.do(); //1boost_fun();   //2cpp_fn();      //3

This topic is closed to new replies.

Advertisement