gz-math
gz-math copied to clipboard
Python bindings + Windows/Conda: dependent libraries of the *.pyd library cannot be found
Environment
- OS Version: Windows 10 Conda
- Source or binary build? Source gz-math7 built according to the tutorial
Continuation of discussion from https://github.com/gazebosim/sdformat/pull/1165#issuecomment-1252967167 .
Python 3.8+ no longer looks into PATH when looking for dependencies of external binary modules. Paths to the dependencies have to be added by calling os.add_dll_directory(). Normally, gz-math7.dll is installed in install/bin, while the *.pyd module is installed in install/lib/python. Therefore, Python doesn't examine install/bin for the dependencies and import gz.math7 fails with error:
ImportError: DLL load failed while importing gz.math7: module not found
Unfortunately, Windows cannot tell which library failed to load, but experimentally, copying everything from install/bin to install/lib/python resolves the issue. However, that is not a suitable solution. If I manually call os.add_dll_directory(abs_path+"/install/bin"), importing the module works.
Now the question is where to put the add_dll_directory() call and what kind of path to pass to it. The most practical way I see is creating wrapper pure python modules which would just call the add_dll_directory() and the load the binary module. This would need some renaming around, but should be the most straight-forward way.
Regarding the path to add, I've seen people on the internet to just add all directories from PATH via add_dll_directory(), but I'd say this kind of goes against the direction set by Python 3.8 (looking in PATH was discarded to increase security; although I'm a bit hesitant if it actually helps if an attacker can still push a malicious .pyd file).
Things to resolve:
- [ ] Where to add
os.add_dll_directory()? - [ ] What kind of path (hardcoded/relative/...) should be passed to the above call?
What kind of path (hardcoded/relative/...) should be passed to the above call?
Related to that, I checked what ROS2-related code does, and in several point it calls:
add_dll_directories_from_env('PATH')
effectively reverting to pre-Python 3.8 behaviour.