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

1 Like

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