MDL SDK API nvidia_logo_transpbg.gif Up
MDL Python Bindings

To give Python developers access to the MDL SDK we offer a low-level Python API generated from the C++ interfaces using SWIG.

The usage of the bindings is meant to be very similar to the original native interface in order to offer the same functionality and to allow porting of C++ applications and examples easily. Furthermore, it allows the developer to refer to the native API documentation to a large extend.

Compiling the Binding Module

The binding is generated using a tool called SWIG. The result of that generation consists of two parts. A C++ file mdl_python_swig.cpp that needs to be compiled and linked against the Python libraries to create the actual binding module. And second, a small Python module pymdlsdk.py that imports the main binding module. It contains documentation, special extension functions that only exist for the Python bindings, and it forwards all function calls to the main binding module.

With the MDL SDK, we provide a CMake-based build system that also compiles the generated C++ code and links it against given Python development libraries to create the main binding module. The reason for compiling this here is that the bindings work only with a specific python version, the one that matches the version of the interpreter that runs your application.

Besides the generated mdl_python_swig.cpp, additional source and header files are required to build the main binding module: mdl_python.h and mdl_python.cpp. These files contain additional utility functions, e.g., to load the native SDK as well as plugins.

After building the bindings successfully, the binding will consist of two files:

  • pymdlsdk.py
  • _pymdlsdk.so (or _pymdlsdk.pyd on windows)

Reference Counting

One major difference between the MDL Python bindings and the MDL SDK is the absence of mi::Handle objects for reference counting. Nevertheless, reference counting is also important in Python, but it happens mostly in the background.

All MDL objects returned by the binding implement the context manager pattern. It is recommended to hold MDL objects using the with statement. It guarantees that the object is freed properly when leaving the with block:

with neuray.get_api_component(pymdlsdk.IMdl_configuration) as cfg:
cfg.add_mdl_path('/home/user/mdl')

Note, that multiple of those blocks can be combined to improve readability:

with neuray.get_api_component(pymdlsdk.IMdl_factory) as mdl_factory, \
mdl_factory.create_type_factory(transaction) as type_factory, \
mdl_factory.create_value_factory(transaction) as value_factory:

The alternative way to make sure MDL objects are disposed properly is to release them manually using their release() function or by assigning None:

context = mdl_factory.create_execution_context()
# ...
context.release() # same as: context = None

Relaying on the fact that Python is taking care of the reference counting is possible as well but not recommended. While this works in well to free local objects when leaving the scope of functions, it might not work well when garbage collection is required. The MDL SDK relies on the disposal of objects in some use cases, for instance when accessing database objects and committing or aborting transactions. To avoid such problems in general, we advise to thoughtfully deal with the lifetime of MDL objects by either using context managers or the manual releasing of objects.

Getting Started

We provide examples for the use of the MDL Python Bindings that illustrate -- in a tutorial manner -- the important interfaces and concepts.

For using the MDL Python bindings the native MDL SDK library as well as the used native plugins need to available. The native files can be added to the the system PATH on Windows, the LD_LIBRARY_PATH on Linux, or DYLD_LIBRARY_PATH on MacOS. The path to the native libraries can also be passed with the load_and_get_ineuray() function. Details on that can be found in the documentation for the Example for Starting and Shutting Down the MDL SDK.

After running CMake and building the bindings, we provide several ways to run and debug the Python examples.

  • In the CMake build directory, a generated vscode-workspace file can be found. This can be opened by Visual Studio Code on all platforms. To run an example, the corresponding Python script has to be the currently opened and visible file. Pressing F5 on the keyboard will ask for a build configuration. This has to match the version selected while building the bindings. After confirming the selection, the example script will start.
  • Alternatively, generated shell scripts called run_example.sh are created in the CMake build directory sub-folders of the individual examples, e.g., examples\mdl_python\start_shutdown\run_example.sh. Running the scripts will add the native libraries to the system PATH, add the MDL Python Bindings to the PYTHONPATH, and start the Python interpreter that was selected during CMake Configure.
  • On Windows, the generated Visual Studio solution will have projects for the Python example as well. They can also be started from the IDE similar to the native examples. However, these projects will allow to debug the C++ side of the bindings or the SDK whereas VS Code can be used to debug the Python code.

Examples