Giving a method as a callback function (gcc 4.7.1) - c++

I'm trying to set a seemingly-simple callback method pointer into a variable and get the following error:
CSerialSniffer.cpp|11|error: cannot convert
‘CSerialSniffer::AsyncRecieverReceived’ from type
‘Nexus::TReceiveCallback (CSerialSniffer::)(Nexus::CData*,
Nexus::IMetaData*)’}’| to type ‘Nexus::typeAsyncReceiverCallback {aka
Nexus::TReceiveCallback ()(Nexus::CData, Nexus::IMetaData*)}’|
Here is the set statement:
typeAsyncReceiverCallback l_pPointer = AsyncRecieverReceived;
And I have the following defined:
typedef TReceiveCallback (*typeAsyncReceiverCallback)(CData *a_pData, IMetaData *a_pMetaData);
class CSerialSniffer
{
...
public:
Nexus::TReceiveCallback AsyncRecieverReceived(Nexus::CData *a_pData, Nexus::IMetaData *a_pMetaData);
...
}
I've been at this for hours now, any ideas?
In response to answers:
I have the same callback mechanism here:
typedef void (*EnqueueCallback)( PData *pd );
class SomeClass
{
...
public:
void enqueue( PData *pd );
...
};
class CSerialSniffer
{
...
public:
void set_enqueue_callback(EnqueueCallback a_pEnqueueCallback );
...
}
SomeClass::SomeFunction(){
this->serialSniffer->set_enqueue_callback(this->enqueue);
}
And it compiles well.
What's the difference between the two?

Your CSerialSniffer::AsyncRecieverReceived is a member function. It cannot be used without an object, so either you make it a free function (outside the class), or a static function:
class CSerialSniffer
{
...
public:
static Nexus::TReceiveCallback AsyncRecieverReceived(
Nexus::CData *a_pData,
Nexus::IMetaData *a_pMetaData);
...
};
typeAsyncReceiverCallback l_pPointer = &CSerialSniffer::AsyncRecieverReceived;
A better alternative with C++11 is to use a std::function<> instead:
typedef std::function<TReceiveCallback(CData*,IMetaData*)>
typeAsyncReceiverCallback;
Now you can create a free function by binding an object as the first argument of the member function:
CSerialSniffer snivver;
auto callback = std::bind(
std::mem_fun( &CSerialSniffer::AsyncRecieverReceived ),
&snivver );
These goodies are in ther <functional> header.

Your callback declaration
typeAsyncReceiverCallback
is regular function, but
AsyncReceiverReceived
is a method (i.e. it NEEDS "this" pointer and there's no way it can get it this way in c++).
Either change AsyncReceiverReceived to static or use the observer pattern.

Related

member function pointer - how to do this?

I have the following:
class NetRequest: public QObject {
Q_OBJECT
public:
NetRequest(QString postData, void(BrowserApp::*f)(QByteArray));
QString postData;
void (BrowserApp::*fn)(QByteArray);
public slots:
void requestFinished(QNetworkReply *r);
}
and the cpp is:
NetRequest::NetRequest(QString postData, void(BrowserApp::*f)(QByteArray)) {
this->postData = postData;
this->fn = f;
}
void NetRequest::requestFinished(QNetworkReply *r) {
QByteArray data;
fn(data);<--- this doesn't work
}
I am trying to call the function "fn" in requestFinished but the compiler doesn't let me - what am I please doing wrong?
Thank you for all your help!
When you have a pointer-to-member-function, in order to call through it you must also have a pointer to the object you are using for the call.
But your code:
fn(data);
Has no such object pointer. You probably are assuming that an object is associated with the member function pointer -- but it isn't.
Try this:
(that->*fn)(data);
that is a pointer to a BrowserApp object. It will need to be either passed in to the requestFinished function, or somehow stored in the NetRequest object -- probably at the same time when fn is set.
I suggest you look into std::function and std::bind. They will help you in many ways when it comes to "function pointers".
Then it would look something like this instead:
class NetRequest: public QObject {
std::function<void(QByteArray)> fn;
// ...
public:
NetRequest::NetRequest(QString postData, std::function<void(QByteArray)> f) {
// ...
fn = f;
}
// ...
};
Now when creating an instance of the NetRequest object, you must use std::bind to bind a function from the BrowserApp class to the std::function object:
BrowserApp app;
NetRequest request("some string", std::bind(&BrowserApp::SomeFunction, app));
The nice thing about using std::function is that the callback function no longer have to be a BrowserApp member function, it can by any function, including lambda expressions.

non-member function pointer as a callback in API to member function

I'm using an API that requires me to pass a function pointer as a callback. I'm trying to use this API from my class in C++ but I'm getting compilation errors.
The API definition is:
typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);
__declspec(dllimport) int __stdcall set_stream_callback(
STREAM_CALLBACK streamCB, void *userdata);
One example file, provided by the third party, is:
void __stdcall streamCB(void *userdata)
{
// callback implementation
}
int main(int argc, const char argv[])
{
int mid = 0;
set_stream_callback(streamCB, &mid);
}
And that works fine.
However when I try to use that in a class, I have an error:
error C3867: 'MyClass::streamCB': function call missing argument list;
use '&MyClass::streamCB' to create a pointer to member
The suggestion to use
&MyClass::streamCB
doesn't work.
I understood that the set_stream_callback only accepts a non-member function.
The problem is very similar to
How can I pass a class member function as a callback?
in which Johannes makes a concise suggestion, however I do not understand it very well. Could anyone expand a bit, if I am correct that it is relevant to this question?
I have tried:
void __stdcall MyClass::streamCB(void *userdata)
{
// callback implementation
}
static void MyClass::Callback( void * other_arg, void * this_pointer ) {
MyClass * self = static_cast<ri::IsiDevice*>(this_pointer);
self->streamCB( other_arg );
}
//and in the constructor
int mid = 0;
set_stream_callback(&MyClass::Callback, &mid);
But
error C2664: 'set_stream_callback' : cannot convert parameter 1 from
'void (__cdecl *)(void *,void *)' to 'STREAM_CALLBACK'
How do I get around this?
Edit1: Also, I want to use userdata inside the streamCB callback.
The idea of calling a member function from a callback taking only non-member functions is to create a wrapper for you member function. The wrapper obtains an object from somewhere and then calls the member function. If the callback is reasonably well designed it will allow you to pass in some "user data" which you'd use to identify your object. You, unfortunately, left out any details about your class so I'm assuming it looks something like this:
class MyClass {
public:
void streamCB() {
// whatever
}
// other members, constructors, private data, etc.
};
With this, you can set up your callback like so:
void streamCBWrapper(void* userData) {
static_cast<MyClass*>(userData)->streamCB()
}
int main() {
MyClass object;
set_stream_callback(&streamCBWrapper, &object);
// ...
}
There are various games you can play with how to create the streamCBWrapper function (e.g., you can make it a static member of your class) but all come down to the same: you need to restore your object from the user data and call the member function on this object.
You can achieve what you want to do by turning the userdata into a property of MyClass. Then you don't have to pass it to MyClass::Callback, which would be impossible, since you can only pass one parameter, and it would be the object instance.
Here's an example.
void __stdcall MyClass::streamCB()
{
// callback implementation
}
static void MyClass::Callback(void * this_pointer ) {
MyClass * self = static_cast<MyClass>(this_pointer);
self->streamCB();
}
MyClass::MyClass(void *userdata) {
// do whatever you need to do with userdata
// (...)
// and setup the callback at C level
set_stream_callback(&MyClass::Callback, (void *)this);
}
In your example, the int mid variable would become a property of that class, and thus be accessible from the callback implementation streamCB.

Combining function, bind, c++ and managed code

I have a c++ function which is expecting a function object (AuthenticateNotifyFunc) to be passed to it thus:
class lc_Authenticate
{
public:
typedef enum {
kAbort,
kContinue
} lc_AuthenticateStatus;
typedef std::tr1::function<lc_AuthenticateStatus (const string &msg)> AuthenticateNotifyFunc;
bool Authenticate(lc_AuthenticateParams &params,
AuthenticateNotifyFunc notifyFunc);
}
Within a managed c++ project, I am attempting to define a parameter to pass to the above function thus:
public ref class Form1 : public System::Windows::Forms::Form
{
public:
lc_Authenticate::lc_AuthenticateStatus UpdateStatus(const string &msg)
{
<<DO SOMETHING>>
return(lc_Authenticate::kContinue);
}
void test()
{
string appKey, appSecret;
appKey = GetString(this->appKeyTextBox->Text);
appSecret = GetString(this->appSecretTextBox->Text);
lc_Authenticate dbauth;
lc_AuthenticateParams params(appKey, appSecret);
// DOESN'T COMPILE won't let me take address of member function
// or know about _1
lc_Authenticate::AuthenticateNotifyFunc func =
std::tr1::bind(&Form1::UpdateStatus, this, _1);
dbauth.Authenticate(params, func);
}
};
So I am trying to implement a generic method of passing a function to a c++ method in such a way that it doesn't care whether the passed function is static or a member function. And I'm not clear how do do this from managed code.
You cannot bind to an instance method of a managed class by design. The garbage collector moves the object around when compacting the heap, causing this to change. You'll need to use a managed delegate. So you can't avoid a native helper class that provides the stable callback you need for your function<>. You can get back to managed code from there with Marshal::GetFunctionPointerForDelegate().

Pass any member function of any class as a Callback function

I'm working on a OpenGL menu which contains some buttons. I want to be able to associate an action (member function (with a fixed signature) of any class!) to a button which gets executed when the button is pressed. I can do it right now but only for one type. I want to be able to use any member function of any class for my callback.
Right now I'm doing it like this:
#define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this )
I can then create a button like this:
Button* b = new Button("Bla", BUTTONCALLBACK(functionIWanttoCall));
The Callback function has the following signature:
void callback(Button* source);
When I press the button I can execute the callback function which I passed.
I had a look at boost::bind but I couldn't really find a way to tackle the problem. Furthermore all my classes are derived from a class Object so I thought about a void* which I could convert to the right class with some typeid hack but I was unable to get it working. At the end I always had the problem that I couldn't completly eliminate the class type of the callback function (which would be necessary to save the function pointer in my button class) and still being able to call the function.
Do you have any idea how to tackle this problem?
Don't use pointers, use boost::function together with boost::bind (or std::function and std::bind if C++0x), something like
// in Button class (or whatever signature you need)
Button(const std::string&, boost::function<void(Button*)> callback) // ...
// you can then use callback as a function
// in calling code
Button *b = new Button("..", boost::bind(&Class::func, this));
You should use a function<void(Button*)> object. These are run-time polymorphic and can be used with any object that supports void operator()(Button*). You can find one in Boost, TR1 and C++0x. boost::bind works well with these objects.
Well, the easiest way would be with virtual functions, if you don't want to pull in Boost or don't have access to C++0x.
#include <iostream>
// fwd declare
class Button;
class BtnCallbackBase{
public:
virtual void operator()(Button*) = 0;
};
template<class C>
class BtnCallback : public BtnCallbackBase{
private:
typedef void (C::*callback_func)(Button*);
C* _object;
callback_func _onclick;
public:
BtnCallback(C* obj, callback_func func)
: _object(obj)
, _onclick(func)
{}
virtual void operator()(Button* btn){
(_object->*_onclick)(btn);
}
};
class Button{
public:
Button()
: _onclick(0)
{}
void Click(){
if(_onclick != 0)
(*_onclick)(this);
}
template<class C>
void RegisterCallback(C* obj, void (C::*func)(Button*)){
// cleanup old callback, deleting null pointer is a noop
delete _onclick;
_onclick = new BtnCallback<C>(obj,func);
}
~Button(){
delete _onclick;
}
private:
BtnCallbackBase* _onclick;
};
class MyClass{
public:
void ExampleCallback(Button* btn){
std::cout << "Callback works!\n";
}
};
int main(){
Button btn;
MyClass test;
btn.RegisterCallback(&test, &MyClass::ExampleCallback);
btn.Click();
}
Full example on Ideone.
If you want a solution to your problem without using Boost library / without using new C++ features then one of the best choice is Generic Callbacks Dispatcher discussed by Danny Kalev / Herb Sutter.
http://www.gotw.ca/gotw/083.htm

C++ Passing a class as a parameter

I'm wondering if it's possible to pass a class as a parameter in c++.
Not passing a Class Object, but the class itself which would allow me to use this class like this.
void MyFunction(ClassParam mClass)
{
mClass *tmp = new mClass();
}
The above is not real code, but it hopefully explains what I'm trying to do in an example.
You can use templates to accomplish something similar (but not exactly that):
template<class T>
void MyFunction()
{
T *tmp = new T();
}
and call it with MyFunction<MyClassName>().
Note that this way, you can't use a "variable" in place of T. It should be known at compile time.
C++ does not store meta data about classes as other languages do. Assuming that you always use a class with a parameterless constructor, you can use templates to achieve the same thing:
template <typename T>
void MyFunction()
{
T* p = new T;
}
You could also pass in a function pointer that when called creates an instance of whatever you want and returns that.
void MyFunction(ClassCreatorPtr makeClassFn)
{
void * myObject = makeClassFn();
}
You'd need to have it return a pointer to a base class to do anything really interesting with it.
You are looking for templates
An alternative to templates is to use a lambda closure with C++11. Here's my preference.
// in header file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator);
// in source file
IClass * MyFunctionThatDoesStuff(const IParams & interface_params,
std::function<IClass * (const IParams & interface_params)> cls_allocator) {
// Some processing. Perhaps the interface_params are generated
// inside this function instead of being passed to it.
IClass * mCls = cls_allocator(interface_params);
// Do whatever with mCls
return mCls;
}
// Somewhere else in the code.
{
Param1Type param1 = whatever1;
Param2Type param1 = whatever2;
// param1, param2, etc. are parameters that only
// SomeClsDerivedFromIClass constructor knows about. The syntax &param1
// achieves the closure.
// interface_param1 is common to all classes derived from IClass.
// Could more than one parameter. These parameters are parameters that
// vary from different calls of MyFunctionThatDoesStuff in different
// places.
auto cls_allocator =
[&param1, &param2](const IParams & interface_params)->IClass * {
return new SomeCls1DerivedFromIClass(interface_params,
param1, param2);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
// Somewhere else in the code again.
{
ParamXType paramX = whateverX;
ParamYType paramY = whateverY;
auto cls_allocator =
[&paramX, &paramY](const IParams & interface_params)->IClass * {
return new SomeCls2DerivedFromIClass(interface_params,
paramX, paramY);
};
IClass * mCls = MyFunctionThatDoesStuff(interface_params,
cls_allocator);
}
The above code idea works well for a quick builder pattern or some factory pattern variation. The lambda is basically a factory method. To make it even more dynamic you can use auto for parameter typing. Something like this.
auto * MyFunctionThatDoesStuff(const auto & interface_params,
std::function<auto * (const auto & interface_params)> cls_allocator);
I'm coming at this from Python influence where you can just pass the class type to the function.
You can create a static factory method on your class(es) that simply returns a new instance of the class and then you can pass around pointers to that function similarly to what you want to do in your example. Return types are covariant, so if all your classes implement the same interface, you can have the function pointer return that interface. If they don't all have a common interface, you'll probably be left with returning void *. Either way, if you need to use the specific subclass, you'll have to dynamic_cast.