How to write a custom function that uses VTK C++ and then use it in Python?

What is the process to write a custom function using VTK in C++ (it’s a time critical function) and then use it’s bindings in Python?
I think I saw some information about this in the past but can’t seem to find it again.
Is the best solution to clone VTK, write the function and then compile the entire library or is there a simpler method that allows to write smaller and contained modules?
Thank you very much in advance.

VTK has an example for this. Note that wrapping only works on “VTK Modules” , not arbitrary code, because of the associated data.

2 Likes

Thank you very much Ben, from a Typescript and Python dev, I am not sure how to use CMake and build my module. Is there a tutorial or anything that I can read or follow?

I am running CMake but it is failing on VTK_DIR:
VTK_DIR-NOTFOUND

I am pointing to the VTK repo folder but I am not sure if I need to build VTK first or what are the steps from here to a module that I can use in Python.

I am sorry for the noob questions on this topic but even the slightest help would be very welcomed.

Yes, you’ll need to build VTK first. You can then point VTK_DIR to the build directory. VTK-specific build information is here. You’ll want to at least turn on VTK_WRAP_PYTHON. It’s not clear what C++ modules you want, but you can turn them on as needed (VTK_MODULE_ENABLE_* flags).

1 Like

You should also be able to build the “Modules/Wrapping” example if you download a recent vtk-python wheel and its corresponding SDK from the VTK download site.

Steps are as follows. I did this with the macOS SDK, so YMMV if you use a different SDK.

  1. Copy “Examples/Module/Wrapping/” from the VTK source tree into your own directory, e.g. call it “WrappingExample”.

  2. Make a new, empty directory called “WrappingExampleBuild” which you will use for doing the compilation. (It’s a recommended practice with CMake to keep the source directory and the build directory separate, such that the source directory contains only source).

  3. Find the “cmake” directory in the SDK, e.g. in the macOS SDK it is in vtk-9.2.0.data/headers/cmake. Set the VTK_DIR to this directory when you run cmake.

  4. Do a build (e.g. on linux/macOS, run “make” in the build directory).

  5. Check to make sure that the python module “vtkWrappable.so/.pyd” was created. For example, in my build it was in lib/python3.7/site-packages/wrapping in the build tree.

  6. Set your PYTHONPATH so that python can find the module. E.g. I used PYTHONPATH=/path/to/WrappingExampleBuild/lib/python3.7/site-packages.

At this point, it should be possible to run Python and do “import wrapping.vtkWrappable”. But as I said, YMMV. I’m sure my list of steps is incomplete, the SDKs might not be mature yet (they’re quite new), and on different operating systems, different paths might have to be set.

2 Likes

Just to complement on what David said, I did a similar thing on Windows, but installing VTK from conda. It all works pretty much out of the box, except point 6 did not work for me on Windows.

I couldn’t find a way to tell python where to look for the new modules, outside the system paths, and the only way to have python see the built objects was to install into the conda environment directly.

Here it says one shoud use os.add_dll_directory() but it didn’t work for me.

Edo

To add some clarification, os.add_dll_directory() does not tell Python where to look for modules. Rather, it tells Python where to look for the DLLs that are used by the modules.

Also note that the python devs didn’t make it easy to use: os.add_dll_directory() returns a cookie, and that cookie must not destruct before the import is performed.

The Python docs recommend a “with” statement:

with os.add_dll_directory("/path/to/dlls") as cookie:
    import mymodule # this module needs the DLLs

One way to think about it is this: as long as cookie exists, a portal is open that allows the process to load the DLLs. As soon as cookie goes out of scope (or if you explicitly call cookie.close()), the portal is closed and the process can no longer load the DLLs.