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
Storing C++ Template Function Definitions in a .Cpp File
Parse (Split) a String in C++ Using String Delimiter (Standard C++)
How Does Guaranteed Copy Elision Work
How to Print Out the Contents of a Vector
Output Unicode Strings in Windows Console App
Pointer to Class Data Member "::*"
Why Does C++ Code For Testing the Collatz Conjecture Run Faster Than Hand-Written Assembly
How to Automatically Generate a Stacktrace When My Program Crashes
What Are the Advantages of List Initialization (Using Curly Braces)
Sorting Output Numbers Without an Array
Given an Integer N. What Is the Smallest Integer Greater Than N That Only Has 0 or 1 as Its Digits
Carry Over Data Without Using for Loop
How to Properly Add Include Directories With Cmake
Undefined Reference to Static Class Member
What Are the Rules About Using an Underscore in a C++ Identifier
How to Take Input to an Array With Unknown Number of Elements