How to Pass a Class Member Function as a Callback

How can I pass a class member function as a callback?

That doesn't work because a member function pointer cannot be handled like a normal function pointer, because it expects a "this" object argument.

Instead you can pass a static member function as follows, which are like normal non-member functions in this regard:

m_cRedundencyManager->Init(&CLoggersInfra::Callback, this);

The function can be defined as follows

static void Callback(int other_arg, void * this_pointer) {
CLoggersInfra * self = static_cast<CLoggersInfra*>(this_pointer);
self->RedundencyManagerCallBack(other_arg);
}

C++ callback using class member

Instead of having static methods and passing around a pointer to the class instance, you could use functionality in the new C++11 standard: std::function and std::bind:

#include <functional>
class EventHandler
{
public:
void addHandler(std::function<void(int)> callback)
{
cout << "Handler added..." << endl;
// Let's pretend an event just occured
callback(1);
}
};

The addHandler method now accepts a std::function argument, and this "function object" have no return value and takes an integer as argument.

To bind it to a specific function, you use std::bind:

class MyClass
{
public:
MyClass();

// Note: No longer marked `static`, and only takes the actual argument
void Callback(int x);
private:
int private_x;
};

MyClass::MyClass()
{
using namespace std::placeholders; // for `_1`

private_x = 5;
handler->addHandler(std::bind(&MyClass::Callback, this, _1));
}

void MyClass::Callback(int x)
{
// No longer needs an explicit `instance` argument,
// as `this` is set up properly
cout << x + private_x << endl;
}

You need to use std::bind when adding the handler, as you explicitly needs to specify the otherwise implicit this pointer as an argument. If you have a free-standing function, you don't have to use std::bind:

void freeStandingCallback(int x)
{
// ...
}

int main()
{
// ...
handler->addHandler(freeStandingCallback);
}

Having the event handler use std::function objects, also makes it possible to use the new C++11 lambda functions:

handler->addHandler([](int x) { std::cout << "x is " << x << '\n'; });

Python: Passing a class member function to another class's callback

This is a little confusing because of your wording. Are you actually trying to pass a class in as you say, or an instance of that class as you seem to be doing? Which class is rotaryChange defined in?

Anyway, it looks like what you're actually trying to do is pass self.rotaryChange as a callback.

This already works, without any changes. self.rotaryChange is a bound method, meaning it knows what that self was when it was created, and will pass it when it's called. This may be easier to see with an example:

>>> class Spam:
... def eggs(self):
... pass
>>> spam = Spam()
>>> spam
<__main__.Spam at 0x119947630>
>>> spam.eggs
<bound method Spam.eggs of <__main__.Spam object at 0x119947630>>

Notice that it's a bound method of the spam object. When you call spam.eggs(), that spam object will be passed as the self argument.

This means you don't need to pass a host in, because it's already available as self. And, since that's the only thing you do with host, you don't need to pass around host in the first place. Which means you can revert all of your changes to the library code.

You do need to define your callback method as a proper method, with self as the first argument. But that's it. Then you can just pass rotaryCallback=self.rotaryChange to the constructor, and everything will work.

Pass Member Function To glfwSet*Callback

Only static member functions can be used like this in GLFW, instead, you can use glfwGetWindowUserPointer and glfwSetWindowUserPointer to provide access to the underlying class object in these situations if you require it.

#include <GLFW/glfw3.h>

//
//
// Event Receiver Framework

enum EventTypes {
Keyboard = 1,
Mouse = 2
};

struct Event {
EventTypes Action;
// Other Event Related Values
};


class EventReceiver {
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
Event NewEvent;
NewEvent.Action = EventTypes::Keyboard;
static_cast<EventReceiver*>(glfwGetWindowUserPointer(window))->OnEvent(NewEvent);
}

public:
virtual void OnEvent(Event& NewEvent) = 0;
friend class MyApplication;
};

//
//
// Application Framework

class MyApplication {
GLFWwindow* window;
public:
void SetEventReceiver(EventReceiver* EventHandler) {
glfwSetWindowUserPointer(window, EventHandler);
glfwSetKeyCallback(window, &EventReceiver::key_callback);
}

};

//
//
// User-Defined Event Receiver

class MyEventReceiver : public EventReceiver {
public:
void OnEvent(Event& NewEvent) {
if (NewEvent.Action == EventTypes::Keyboard) {
// Custom Event Actions
}
else if (NewEvent.Action == EventTypes::Mouse) {
// Custom Event Actions
}
}
};

//
//
// Main

int main() {
MyEventReceiver _Events;
MyApplication _App;
_App.SetEventReceiver(&_Events);
//
// Do logic
//
return 0;
}

How to make a callback in C++: use a class member function as a parameter [duplicate]

Here is a working way to do that:

void myOtherFunction(std::function<void()> oneOfMyFunctions) {
oneOfMyFunctions();
}

And inside my class:

myOtherFunction([&] {
oneOfMyFunctions();
});

Some explanations:
In std::function<void()>, void is what is returned by the function and () contains the types of its parameters (mine is empty because it doesn't have any).

In the 2nd code I am using a lambda to keep the context, as a bind would do (but lambdas replace them).

Using a C++ class member function as a C callback function

You can do that if the member function is static.

Non-static member functions of class A have an implicit first parameter of type class A* which corresponds to this pointer. That's why you could only register them if the signature of the callback also had the first parameter of class A* type.

Pass method as callback from one class to other class

See c++ - <unresolved overloaded function type> for details.

To quote the answer:

In C++, member functions have an implicit parameter which points to
the object (the this pointer inside the member function). Normal C
functions can be thought of as having a different calling convention
from member functions, so the types of their pointers
(pointer-to-member-function vs pointer-to-function) are different and
incompatible. C++ introduces a new type of pointer, called a
pointer-to-member, which can be invoked only by providing an object.

Put static on someMethod:

class B
{
private:
A * Aguy;

public:
B();
static void someMethod();
void otherMethod();
};

void B::otherMethod() {
Aguy->setCallBack(B::someMethod);
Aguy->useCallBack(); // adding missing semicolon
}

How to pass a member function as callback param to a function that expects a `typedef-ed` free function pointer?

It is not possible to have a (non-member-) function pointer to a non-static member function. It is also not possible to point a function pointer to a bound function.

Notice how the free function type has an argument void *cbdata. You haven't shown the documentation of the API that you use, but I would be willing to bet that the API follows a common idiom, and the third argument of mg_set_request_handler is also void *cbdata. If my assumption is correct, the same pointer that was passed to registration, will be passed to the handler later. It's purpose is to pass data - such as your HttpServer instance into the callback.

For example:

mg_set_request_handler(ctx_, "/get", [](mg_connection *conn, void *cbdata) {
assert(cbdata);
HttpServer& server = *static_cast<HttpServer*>(cbdata);
server.get_handler_member(conn, cbdata);
}, this);

If get_handler_member has non-public access, then you'll need to use a static member function instead of the lambda that I used in my example. Also, the cbdata argument of get_handler_member is now probably useless and can be removed.

Do remember to keep the HttpServer instance alive as long as the handler is registered.

Also, to re-iterate: This relies on my assumption about the API that you've shown. Consult the documentation carefully.



Related Topics



Leave a reply



Submit