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);
}
How to use class methods as callbacks
Check the callable
manual to see all the different ways to pass a function as a callback. I copied that manual here and added some examples of each approach based on your scenario.
Callable
- A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo, empty(), eval(), exit(), isset(), list(), print or unset().
// Not applicable in your scenario
$this->processSomething('some_global_php_function');
- A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.
// Only from inside the same class
$this->processSomething([$this, 'myCallback']);
$this->processSomething([$this, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething([new MyClass(), 'myCallback']);
$myObject->processSomething([new MyClass(), 'myStaticCallback']);
- Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object at index 0.
// Only from inside the same class
$this->processSomething([__CLASS__, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething(['\Namespace\MyClass', 'myStaticCallback']);
$myObject->processSomething(['\Namespace\MyClass::myStaticCallback']); // PHP 5.2.3+
$myObject->processSomething([MyClass::class, 'myStaticCallback']); // PHP 5.5.0+
- Apart from common user-defined function, anonymous functions can also be passed to a callback parameter.
// Not applicable in your scenario unless you modify the structure
$this->processSomething(function() {
// process something directly here...
});
ES6: How to call a class function from a callback function
function
changes the meaning of this
. One way to fix the problem is to use bind
. However, you'd have to use it twice, because you have two layers of function
. A simple way to solve it is to use arrow functions, which do not change this
:
class MyClass {
constructor() {
this.a = '';
}
init() {
....
$.getJSON(url, (data) => {
$(mySelector).click(() => {
this.classFn();
});
});
}
classFn() {
....
}
}
Using c++ class method as a function callback
Usual pattern is to pass the instance pointer this
into the PVOID pvContext
parameter, then use it within the callback to call a member function.
public class Camera
{
// ...
void ThisTransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw);
static void __stdcall TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext);
};
Set the callback as
StTrg_SetTransferEndCallback(cameraHandle, TransferEndCallback, this);
Then write the static callback to dispatch it to the member function
void __stdcall Camera::TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext)
{
((Camera *)pvContext)->ThisTransferEndCallback(hCamera, dwFrameNo, dwWidth, dwHeight, wColorArray, pbyteRaw);
}
The above doesn't include error checking etc.
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'; });
Passing class method as callback to another class in javascript
I changed the foo and bar to Form
and Popup
:
1) Quick — and possibly dirty — solution:
You can send this
as the second argument to .fire()
:
class Form {
constructor() {
this.property = 'yes';
}
eventMethod() {
let popup = new Popup();
popup.fire(this.endMethod, this);
}
endMethod(values, that) {
console.log(values + that.property);
}
}
class Popup {
constructor() {
this.property = 'no';
}
fire(callback, that) {
let value = 'message';
callback(value, that);
}
}
let form = new Form();
form.eventMethod();
How to use a callback function in a class with inheritance
Found a way to do the same thing but with a none static method
ES6 style allows you to use new features, such as super keyword. super keyword it's all about parent class context, when you are using ES6 classes syntax.
class Parent {
numbers: number[];
constructor(numbers: number[]) {
this.numbers = numbers;
}
protected iterateNumbers(predictionCallback: (nb: number) => void): void {
for (const nb of this.numbers) {
predictionCallback(nb);
}
}
protected inc(nb: number): number {
return nb++;
}
}
class Child extends Parent {
constructor(numbers: number[]) {
super(numbers)
}
getNumbers() {
this.iterateNumbers(this.displayNumber);
}
private displayNumber(nb: number): void {
console.log(super.inc(nb));
}
}
const c = new Child([1, 2, 3, 4, 5]);
c.getNumbers();
Calling C++ class methods from C using callbacks
The classical C way of passing callbacks is to pass two values: a pointer to the callback itself, and an opaque pointer which will be passed to the callback as an additional argument (take a look at qsort_r
for example). When interfacing with C++, that opaque value may be used as instance pointer; you will only need to write a thin wrapper:
class B {
void my_callback(int arg);
static void my_callback_wrapper(int arg, void *u) {
((B*)u)->my_callback(arg);
}
};
// or even:
extern "C" void my_callback_wrapper(int arg, void *u) {
((B*)u)->my_callback(arg);
}
and pass a pointer to the wrapper, along with a pointer to the object, to the C part. Be careful to use the exact same class type on both sides and not base/derived classes, for example.
Note that while it may be possible to get a pointer to the (non-static) method itself, on some compilers (tested on MSVC a long time ago) they have a special calling convention so that the pointer will not be compatible with any normal function pointer.
Node.JS: class method as callback
You need to bind
a particular this
context to the method before you can use it as a callback, or the caller will provide its own this
(which may not be what you expect).
The simplest way is to:
mysql.query([...], this._method1QueryCallback.bind(this))
Assuming you know this
is the correct scope when you call mysql.query
.
That does make it difficult to later unbind the callback, which can be a problem if you are setting up an event handler. In that case, you can do something like:
this._method1QueryCallback = this._method1QueryCallback.bind(this);
somewhere in your constructor, or just prior to passing the callback.
Related Topics
Concatenation with Addition in It Doesn't Work as Expected
How to Force Laravel Project to Use Https for All Routes
Convert Jpg/Gif Image to Png in PHP
PHP "Pretty Print" HTML (Not Tidy)
Http_Build_Query with Same Name Parameters
PHP Printed Boolean Value Is Empty, Why
How to Regex-Replace Multiple <Br /> Tags with One <Br /> Tag
PHP - Plus Sign with Get Query
PHP Filesize Reporting Old Size
How to Access the Form's 'Name' Variable from PHP
Laravel Tokenmismatchexception in Ajax Request
Parse Error: Syntax Error, Unexpected '(', Expecting ',' or ';' In
PHP Regular Expression to Match Lines Starting with a Special Character