How to Use Class Methods as Callbacks

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



Leave a reply



Submit