member function pointer - how to do this? - c++

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.

Related

Setting a pointer to another pointer breaks reference somehow

Based on my understanding of pointers here, currentDancer and pushups should be the same reference. And yet if I set currentDancer I can't use it.
Dancer *currentDancer;
DancerPushups pushups; // DancerPushups inherits from public Dancer
void setup() {
pushUps.init(FL1, FL2, FR1, FR2, BR1, BR2, BL1, BL2);
currentDancer = &pushups; // try to set pushups as the current dancer
}
void loop() {
pushups.onBeatStart(duration); // works great! :D
currentDancer->onBeatStart(duration); // does nothing D:
}
What part of pointer handling am I failing here? How can I get Dancer *currentDancer to point to an arbitrary instance that I already have created?
UPDATE:
Is this an inheritance issue?
void Dancer::onBeatStart(float duration) {
// no-op
}
// DancerPushups : public Dancer
void DancerPushups::onBeatStart(float duration) {
all(the, cool, stuff, that, isnt, happening);
}
Because I'm casting the DancerPushups to a Dancer* type, am I not running my subclasses method?
Sounds like onBeatStart is not a virtual member function. When you call currentDancer->onBeatStart(), you are calling the base class implementation, which, as you have shown, does nothing.

boost member function pointers

I am very new to the boost libraries.
I was trying to accomplish something for a graphical program, by binding the callbacks passed
to glutDisplayFunc(), etc to a single class.
I wanted to accomplish this without having some constant global class object.
To explain in code:
class CallbackHolder {
public:
void dostuff(void) {
// etc.
}
};
void bind() {
glutIdleFunc((new CallbackHolder())->dostuff);
}
I know this is possible through the usage of boost::bind and boost::function.
One issue I did see however was converting the boost::function back to a normal function pointer.
How would you accomplish this?
You can't convert from boost::function to a normal function pointer, and you can't convert from a member function pointer to a normal function pointer. There are workarounds for functions accepting callback where you can provide user data.
Unfortunately the glut interface doesn't let you provide user data. This means you're stuck with the ugliest solution, using a global variable and a normal function.
class CallbackHolder {
public:
void dostuff(void) {
// etc.
}
};
CallbackHolder * g_callbackHolder = NULL;
void call_callback_holder(void) {
if(g_callbackHolder) g_callbackHolder->dostuff();
}
void bind() {
g_callbackHolder = new CallbackHolder();
glutIdleFunc( &call_callback_holder );
}

Giving a method as a callback function (gcc 4.7.1)

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.

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