6

I'm trying to work with a library that is compiled to /usr/local/lib/libName.so but while running the python script that needs this file for:

from ctypes import CDLL
[...]
__lib = CDLL('libName.so')

I get:

OSError: libName.so: cannot open shared object file: No such file or directory

So i would like to know where i need to copy the .so file so that this CDLL call works properly.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
meissner_
  • 556
  • 6
  • 10

1 Answers1

7

[Python.Docs]: ctypes - A foreign function library for Python, uses [Man7]: DLOPEN(3) in order to load libraries, which delegates the loading (and implicitly finding) task to the Nix loader.

The paths to search for .sos is very well explained in [Man7]: LD.SO(8). Here's what it states about default ones:

  • In the default path /lib, and then /usr/lib. (On some 64-bit architectures, the default paths for 64-bit shared objects are /lib64, and then /usr/lib64.)

Ways (most common) to solve your problem:

  1. Pass the full path to CDLL:

    __lib = CDLL("/usr/local/lib/libName.so")
    
  2. Tell the loader to also search /usr/local/lib for .sos, by adding it to ${LD_LIBRARY_PATH} env var for the Python process that wants to load it:

    • export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib
      # ...
      python
      
    • LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib python
      
  3. Copy the .so in one of the default search paths (although I wouldn't recommend it, but if you must, copy it in /usr/lib instead of /lib (although on some OSes they could be symlinked))

Might also worth reading [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer).

CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • Can it be done from Python? Set the environment variable via `os.environ`? Seems like it can't. – Tomasz Gandor Jun 09 '19 at 05:37
  • @TomaszGandor: The loader does it before actually starting the process, so simply changing it via `os.environ`. I'm not aware of a way doing it at *OS* level (but this doesn't mean that there isn't one), so from *Python* you could do it starting another process (but this would only be a workaround). – CristiFati Jun 09 '19 at 14:46
  • Good idea! I would have to restart myself in a changed environment. Preferably before any serious work was started. Although it smells to me like "UAC elevated self restarting under Windows", but I will try it. Thanks! – Tomasz Gandor Jun 09 '19 at 16:56
  • @CristiFati: You could do it from Python relatively easily with a shebang; just a few lines. I'll expand on this if anyone should find it helpful. – Zach Gates May 12 '22 at 10:39