vtkCallbackCommand for class member functions

Hello VTK Community.

I’m looking for a way, to register a class member function as a callback to a vtkCallbackCommand like that:

class foo
{
public:
   void bar(vtkObject* caller, unsigned long eId, void* clientData, void* callerData);
}

Foo::Foo()
{
   auto callbackCommand = vtkSmartPointer<vtkCallbackCommand>::New();
   callbackCommand->SetCallback(bar);
   this->AddObserver(vtkCommand::<event-name>, callbackCommand);
}

Using vtkCallbackCommand I get an error like:

argument of type void (foo::*)(vtkObject *, unsigned long, void *, void *) is incompatible with parameter of type void (*)(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)

It seems that such functionality is already implemented within Paraview (?), see: ParaView: vtkMemberFunctionCommand< ClassT > Class Template Reference

Is there already a similar implementation in VTK C++ which I’m missing?

I believe the issue here is that the bar function needs an object to be invoked on. If you change the bar function such that it is a static function it should work. If you need bar to be a non static function you can pass the object it should be invoked on via the clientData pointer. Here is an explanation for that: https://vtk.org/Wiki/VTK/Tutorials/Callbacks

If you are using Qt you can have a look at this: vtkEventQtSlotConnect: Slot not being called - #2 by nicfel and the example https://kitware.github.io/vtk-examples/site/Cxx/Qt/EventQtSlotConnect/

Hi @nicfel

Ok, that’s what I thought so too. But i indeed need a non-static function to be the callback.

The clientData is the way to go here I think … I hoped there would be a “cleaner” way already implemented in VTK, as ParaView seems to have that functionality.

Thanks, for your answer!

Best Regards
Philipp

You can register an observer callback method directly with vtkObject (see the documentation for vtkObject::SetObserver).

When used this way, the callback has no clientData (just callerData):

void foo::bar(vtkObject* caller, unsigned long eId, void* callerData);

Perfect - that’s what I was looking for.

So when using something like this:

foo:foo()
{
   foo->AddObserver(vtkCommand::<event-name>, this, &foo::bar);
}

The callback is able to run the member function, which enables me to use member variables aswell, without setting clientData of the AddObserver() call from my initial post.

Thank you @dgobbi

Best Regards
Phlipp