1

From https://en.wikipedia.org/wiki/Foreign_function_interface

the ctypes module can load C functions from shared libraries/DLLs on-the-fly and translate simple data types automatically between Python and C semantics as follows:

import ctypes
libc = ctypes.CDLL( '/lib/libc.so.6' )   # under Linux/Unix
t = libc.time(None)                      # equivalent C code: t = time(NULL)
print t

On Lubuntu 18.04

$ whereis libc
libc: /usr/lib/x86_64-linux-gnu/libc.a /usr/lib/x86_64-linux-gnu/libc.so /usr/share/man/man7/libc.7.gz

$ locate libc.so
/lib/i386-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/usr/lib/x86_64-linux-gnu/libc.so

$ ls -l /usr/lib/x86_64-linux-gnu/libc.so
-rw-r--r-- 1 root root 298 Apr 16 16:14 /usr/lib/x86_64-linux-gnu/libc.so

I was wondering why loading the libc shared library has "'LibraryLoader' object is not callable" error?

$ python3 --version
Python 3.6.5

$ python3

>>> import ctypes
>>> libc=ctypes.cdll("/usr/lib/x86_64-linux-gnu/libc.so")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'LibraryLoader' object is not callable


>>> libc=ctypes.cdll("/lib/x86_64-linux-gnu/libc.so.6")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'LibraryLoader' object is not callable


>>> libc=ctypes.cdll("/lib/i386-linux-gnu/libc.so.6")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'LibraryLoader' object is not callable

See also https://unix.stackexchange.com/questions/449107/what-differences-and-relations-are-between-the-various-libc-so

Tim
  • 1
  • 141
  • 372
  • 590

1 Answers1

4

You're confusing lower case cdll (which is a LibraryLoader) with upper case CDLL, which is the constructor for shared libraries.

This code will work as expected:

libc = ctypes.CDLL("/lib/x86_64-linux-gnu/libc.so.6")
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • Wouldn’t it be better to load `/lib/x86_64-linux-gnu/libc.so.6`? Otherwise the Python script will need the C library development packages at run-time... – Stephen Kitt Jun 11 '18 at 14:05
  • @StephenKitt I think that's outside of the scope of the question. It's about how to load a library correctly, not which one is the best. – Aran-Fey Jun 11 '18 at 14:07
  • Agreed; I was just trying to reduce the risk of copy-pasta ;-) (and it would make the answer correspond to the example which started all this). – Stephen Kitt Jun 11 '18 at 14:19
  • Thanks. What is the difference between a LibraryLoader (e.g. `cdll`) and the constructor for shared libraries (e.g. `CDLL`)? Can they both do the same thing? – Tim Jun 13 '18 at 11:58
  • @Tim I'm not sure what to say to that. It's all explained in the documentation, so I can really only repeat the information from there: A LibraryLoader is an object that lets you load libraries through attribute access. `CDLL` (along with `WinDLL` and the others) is the class of those loaded libraries. Basically, `cdll.foo == CDLL('foo')`, `windll.foo == WinDLL('foo')`, etc. – Aran-Fey Jun 13 '18 at 12:03
  • Thanks. Do we need to create `cdll.foo` first? If yes, is it done by `cdll.LoadLibrary("foo")`? – Tim Jun 13 '18 at 13:19
  • @Tim You don't need to create it first. The whole point of the LibraryLoader is that it creates the library for you when you access it. And no, `cdll.LoadLibrary("foo")` doesn't create `cdll.foo`. As [the documentation](https://docs.python.org/3/library/ctypes.html#ctypes.LibraryLoader.LoadLibrary) states, the `LoadLibrary` method always creates a new instance, whereas `cdll.foo` will always be the *same* instance. – Aran-Fey Jun 13 '18 at 13:30
  • Thanks. I am still too slow to understand your comment. I thought it would be better to create a new post https://stackoverflow.com/questions/50838633/how-is-the-attribute-of-the-loader-instance-cdll-created, to avoid the length of comments. – Tim Jun 13 '18 at 14:43
  • @Aran-Fey I am not sure how `cdll.foo` is assigned a value to. Could you look again at https://stackoverflow.com/questions/50838633/how-is-the-attribute-of-the-loader-instance-cdll-created/? – Tim Jun 16 '18 at 15:23
  • @StephenKitt Thanks. I'd appreciate again if you could take a look at https://stackoverflow.com/questions/50838633/how-is-the-attribute-of-the-loader-instance-cdll-created/50840871 – Tim Jun 16 '18 at 15:25