Author aixtools@gmail.com
Recipients David.Edelsohn, Michael.Felt, aixtools@gmail.com, martin.panter
Date 2016-05-10.21:25:50
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <ed2cd255-1465-f4bf-2576-c7b5393d8eb3@gmail.com>
In-reply-to <1462688973.52.0.610199997209.issue26439@psf.upfronthosting.co.za>
Content
On 5/8/2016 8:29 AM, Martin Panter wrote:
> Martin Panter added the comment:
>
> Your new patch calls find_library() internally in CDLL(); why?
Because arguments that work for GNU (aka Linux, even though internally 
it is called "posix") will not work for AIX.
> My understanding is CDLL() is a fairly lightweight wrapper around the dlopen() call.
For AIX, the dlopen() call is a front-end for the function 
initAndLoad(). I have not looked in depth at Module/_ctypes (only 
recently found it) and I do not know how much work is being done there 
for the different platforms.
> On Linux, you either pass a full library file name, or an SO-name.
Same for AIX: a full-path library name, relative-path library name, or a 
library name and the library search path (with optional additional 
directories provided via environment variables (LIBPATH or 
LD_LIBRARY_PATH - when it is a FILE, or an archive(member_name) (with 
archive part being full or relative, or stem) and RTLD_MEMBER ORed into 
the mode argument.
> Both these strings can be discovered for compiled objects using e.g.:
Likewise for AIX: - example: an executable - notice how many are named 
shr.o: how is cdll("shr.o") suppossed to know it is libc, or is it libcrypt?

root@x064:[/usr/lib]ldd /usr/sbin/sshd
/usr/sbin/sshd needs:
          /usr/lib/libc.a(shr.o)
          /usr/lib/libcrypto.a(libcrypto.so.1.0.0)
          /usr/lib/libz.a(libz.so.1)
          /usr/lib/libpam.a(shr.o)
          /usr/lib/libdl.a(shr.o)
          /unix
          /usr/lib/libcrypt.a(shr.o)
          /usr/lib/libpthreads.a(shr_xpg5.o)
          /usr/lib/libpthreads.a(shr_comm.o)

Or a file:
./perl-5.14.4/lib/5.14.4/aix-thread-multi-64int/auto/B/B.so needs:
          /usr/lib/libpthreads.a(shr_xpg5.o)
          /usr/lib/libc.a(shr.o)
          /unix
          /usr/lib/libpthreads.a(shr_comm.o)
          /usr/lib/libcrypt.a(shr.o)

Again, cdll("shr.o") is not going to find the correct archive.
> $ ldd build/lib.linux-x86_64-2.7-pydebug/_ssl.so
> 	linux-vdso.so.1 (0x00007fff567fe000)
> 	libssl.so.1.0.0 => /usr/lib/libssl.so.1.0.0 (0x00007f598474c000)
> 	libcrypto.so.1.0.0 => /usr/lib/libcrypto.so.1.0.0 (0x00007f59842d4000)
> 	. . .
>
> So in Python, the SO-name or full path can be used, but not the compile-time name, unless you first pass it through find_library():

>>>> CDLL("libcrypto.so.1.0.0")  # soname
> <CDLL 'libcrypto.so.1.0.0', handle 7f1665e1eb90 at 7f16658f34d0>
>>>> CDLL("/usr/lib/libcrypto.so.1.0.0")  # Full path
> <CDLL '/usr/lib/libcrypto.so.1.0.0', handle 7f1665e1eb90 at 7f1663cddcd0>
>>>> CDLL("crypto")  # Compile-time name
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
>    File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
>      self._handle = _dlopen(self._name, mode)
> OSError: crypto: cannot open shared object file: No such file or directory
>>>> find_library("crypto")  # Some people pass the result of this to CDLL()
> 'libcrypto.so.1.0.0'
Thank you for the explanation of what should be used when. Maybe I 
worked too hard for the current result: (note - 64-bit this time! and 
new member names, even for libc.so)

michael@x071:[/usr/lib]python -m ctypes.util
None
libc.a(shr_64.o)
None
aix.find_library("libiconv.so") libiconv.a(shr4_64.o)
aix.find_library("libintl.so") libintl.a(libintl.so.1)
aix.find_library("libintl.so.1") libintl.a(libintl.so.1)
aix.find_library("libintl.so.2") None :: should be None!
aix.find_library("libintl.so.8") None
<CDLL 'libc.a(shr_64.o)', handle a at 0x7000000002242b0>
<CDLL 'libintl.a(libintl.so.1)', handle b at 0x7000000002242b0>
<CDLL 'libcrypt.a(shr_64.o)', handle c at 0x7000000002242b0>
libcrypt.a(shr_64.o)

Back to Why though.

Ease of use, and portability with existing convention. My experience 
with just two python packages I wanted to port is that cdll("libFOO.so") 
is what is used, and works on GNU. I wanted that to work ASIS. I also 
noticed that sometimes code was explicit about the version (sometimes 
the latest was not right, and the code complained). So, since "short" 
names are preferred, and are portable - those are what programmers tend 
to use. Full-path-names imply an assumption.

dlopen() is not going to know that libc.so is actually libc.a(shr.o) - 
so I call find_library() for portability aka Ease of Use. While it may 
be slightly less performance I am hoping (assuming) cdll("foo") is not 
the most central part of any application - and the overhead is acceptable.

And thanks for the question. It is simple enough to remove now, should 
it be considered a sin.

> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue26439>
> _______________________________________
History
Date User Action Args
2016-05-10 21:25:52aixtools@gmail.comsetrecipients: + aixtools@gmail.com, martin.panter, David.Edelsohn, Michael.Felt
2016-05-10 21:25:51aixtools@gmail.comlinkissue26439 messages
2016-05-10 21:25:50aixtools@gmail.comcreate