gazebosim / gz-math

General purpose math library for robot applications.
https://gazebosim.org/libs/math
Apache License 2.0
52 stars 62 forks source link

Python bindings + Windows/Conda: dependent libraries of the *.pyd library cannot be found #507

Open peci1 opened 1 year ago

peci1 commented 1 year ago

Environment

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:

traversaro commented 1 year ago

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.