Making client-side only C++ class accessible from Python

Question:
How to access C++ class from python that’s client-side only and has no XML file to wrap?

Little background:
As part of our application, I have implemented (via events) C++ class that allows camera to follow object. I have GUI toolbar with buttons for controlling the behaviour, e.g. to enable/disable tracking. This “behavior” class as well as toolbar exists on client side as I’m only interacting with client-side camera and both are part of one plugin. The behavior class is implemented as singleton which registers all existing render views.

Now, we are using python scripts for project files that get loaded on start-up and I’d like to setup the object tracking behaviour there (like, what object to track). So I need to access my C++ singleton from python and interact with the class. However, I haven’t found a way to do that yet. Could anyone point me in direction, maybe existing plugin or documentation?

One thing I noticed when going through existing implementation of some PV python scripts - they import classes from paraview.module namespace. I believe this gives access to any C++ PV class from Python and is basically what I need. However, our custom modules are not listed there and I suppose this is because they come from plugin, not application itself. If there was a way to achieve similar for plugins, that would be perfect.

First question: is your C++ class wrapped in Python?

@ben.boeckel Is it possible to import Python-wrapped classes defined in a plugin? If so, what would the import look like?

First question: is your C++ class wrapped in Python?

How exactly is this done? Is there CMake rule for that or I need to write the wrapper myself? I guess ParaView doesn’t have hand-coded wrapper for each class, that would be lot of effort.

As long as your helper looks mostly like a VTK object, it can be automatically wrapped. I’m not up to date on the particulars of wrapping code in a plugin, though.

There’s the PYTHON_MODULES argument for making pure-Python modules available in the plugin (they’re available as if they were placed in the global import namespace). There’s no support for providing Python-wrapped VTK class APIs as part of a plugin; they’d need to be wrapped using the CMake API manually and then installed properly on its own. There’s probably some work necessary to get those visible to the Python import logic too.

The class that provides camera tracking is currently just a Qt subclass, so you helped me realize I would probably also need to create a helper which is a VTK class and forwards the calls to the Qt one. However, we have other classes that follow VTK interface and I couldn’t really find python namespace (like that modules) in which I could access them directly - they are only available through proxies defined by XML.

Thanks @ben.boeckel for the update. So I was intrigued about this modules namespace which is located under <ParaView-install/lib/python3.5/site-packages/paraview/modules> and seem to wrap ParaView/VTK classes. I couldn’t find rule that produces them just yet, but couldn’t those be used? Or is that what you are calling “using the CMake API manually”? You’re right though that we would still need mechanism to consume this pair of python+.so files somehow.

VTK’s module system will create Python modules under the paraview.modules package. It’s the same way that (much of) the vtkmodules package for VTK itself gets populated. The CMake rules are associated with the vtk_module_wrap_python call. Plugins can’t really access this at all, so they need to handle Python wrapping with their own vtk_module_wrap_python call.

Thanks, might be just what I was looking for. I’ve been also thinking in different direction - instead of wrapping C++ class with Python myself, would it be possible to write ServerManager XML that would instantiate client-side object? There is SourceProxy tag with class=vtkClass attribute which instantiates vtkClass on server and uses SourceProxy (vtkSMSourceProxy) to interact with it. Maybe there are other proxies or tags that I could use, where vtkClass is instantiated on client? Or would it be possible to create my own “proxy” that can be consumed in XML?

Edit: I’ve indeed found an example plugin creating “MyElevationProxy”. Will try to explore this option further.

Just to provide update on this, I have went with the second option.

I’ve created simple subclass of vtkSMProxy that sets Location in constructor to vtkProcessModule::CLIENT. I can then use this subclass in XML in place of <Proxy> and the class in class attribute will get instantiated only on client. Next, I define properties for this proxy as usual and then leverage ServerManager to load this XML and make the proxy available in Python interpreter, which is sufficient for our usecase.

Thanks for the help and giving me some clarity.