paul-nameless / pyfswatch

Python binding to libfswatch
MIT License
10 stars 9 forks source link

import error #8

Open yr-wang-hit opened 2 years ago

yr-wang-hit commented 2 years ago

By from fswatch import Monitor

The error is : undefined symbol: fsw_init_library What happens and how to resolve it? Thanks a lot .

terzeron commented 1 year ago

Hello, I got an error in importing fswatch in silicon mac, macos 12.2. This may be a bug made by combination of both find_library() of ctypes.util and installation path of homebrew of silicon mac.

>>> import fswatch
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/terzeron/.pyenv/versions/tm/lib/python3.10/site-packages/fswatch/__init__.py", line 2, in <module>
    from .fswatch import Monitor
  File "/Users/terzeron/.pyenv/versions/tm/lib/python3.10/site-packages/fswatch/fswatch.py", line 4, in <module>
    from fswatch import libfswatch
  File "/Users/terzeron/.pyenv/versions/tm/lib/python3.10/site-packages/fswatch/libfswatch.py", line 9, in <module>
    fsw_init_library = lib.fsw_init_library
  File "/Users/terzeron/.pyenv/versions/3.10.7/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__
    func = self.__getitem__(name)
  File "/Users/terzeron/.pyenv/versions/3.10.7/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(RTLD_DEFAULT, fsw_init_library): symbol not found

The official documentation of Python ctypes says that

If wrapping a shared library with ctypes, 
it may be better to determine the shared library name at development time, 
and hardcode that into the wrapper module 
instead of using find_library() to locate the library at runtime.

The ctypes.util.find_library() is very system dependent. I think that it's not suitable for dynamic loading of library with name known already.

So I coded like this;

import ctypes
import sys

if sys.platform == "linux":
    lib = ctypes.CDLL("libfswatch.so")
elif sys.platform == "darwin":
    lib = ctypes.CDLL("libfswatch.dylib")
elif sys.platform == "cygwin":
    lib = ctypes.CDLL("cygfswatch-11.dll")
else:
    raise Exception("can't load fswatch library dynamically")

fsw_init_library = lib.fsw_init_library

(I've tested this in Ubuntu Linux and M1 macos and not in cygwin)

Would you fix this problem?

Thank you.

nayyarv commented 1 year ago

Thanks @terzeron it fixed the issue for me (also on a silicon mac).

pengw0048 commented 1 year ago

I think it has to do with the version of python the user runs. By default, find_library() won't be able to find the brew version of fswatch.

However, the brew version of python has an additional search path injected on top of this line in the canonical cpython to make it search under /opt/homebrew/lib. It happens here.

@nayyarv's fix won't work for cases where the libs aren't on the search path either. https://github.com/Homebrew/brew/issues/13481 seems to suggest there's no generic way to make brew-installed libraries globally available.