2016-05-31 24 views
4

Ich bin auf OS X und installiert das Gtk + 3-Paket mit Homebrew.Ist die Reihenfolge, in der dynamische Bibliotheken geladen werden, von Bedeutung?

brew install gtk+3 

Ich kann mit dem ctypes Modul die installierten Bibliotheken in Python laden.

$ python2.6 
Python 2.6.9 (unknown, Oct 23 2015, 19:19:20) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from ctypes import cdll 
>>> cdll.LoadLibrary('/usr/local/lib/libatk-1.0.0.dylib') 
<CDLL '/usr/local/lib/libatk-1.0.0.dylib', handle 7fbd10f1a250 at 10aa> 
>>> cdll.LoadLibrary('/usr/local/lib/libglib-2.0.0.dylib') 
<CDLL '/usr/local/lib/libglib-2.0.0.dylib', handle 7fbd10f0ffb0 at 10aa22dd0> 
>>> ^D 

So weit so gut. Eine Sache, die mich stört ist, dass, wenn ich versuche, die gleichen zwei Bibliotheken oben, aber in einer anderen Reihenfolge zu laden, wirft es eine Symbol nicht gefunden Ausnahme.

$ python2.6 
Python 2.6.9 (unknown, Oct 23 2015, 19:19:20) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from ctypes import cdll 
>>> cdll.LoadLibrary('/usr/local/lib/libglib-2.0.0.dylib') 
<CDLL '/usr/local/lib/libglib-2.0.0.dylib', handle 7fad13d00d60 at 10a688210> 
>>> cdll.LoadLibrary('/usr/local/lib/libatk-1.0.0.dylib') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ctypes/__init__.py", line 423, in LoadLibrary 
    return self._dlltype(name) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ctypes/__init__.py", line 345, in __init__ 
    self._handle = _dlopen(self._name, mode) 
OSError: dlopen(/usr/local/lib/libatk-1.0.0.dylib, 6): Symbol not found: _g_free 
    Referenced from: /usr/local/lib/libatk-1.0.0.dylib 
    Expected in: flat namespace 
in /usr/local/lib/libatk-1.0.0.dylib 
>>> ^D 

So Laden atk zuerst, und dann glib arbeitet. Andersherum nicht. Kann jemand dieses Verhalten erklären?

+1

Ja, C-Bibliotheken sind Reihenfolge-abhängig, mit den Abhängigkeiten später in der Reihenfolge als die Abhängigen. In C mit (sagen wir) libs A B und C, wenn ein in A verwendetes Symbol, das in C gefunden werden sollte, zuerst von einem gleichnamigen Interloper in B maskiert wird. Und bestellt sie als B C A bricht. Hier haben Sie den letzteren Fall, wo libatk A ist, das Symbol _g_free ist und glib * definitiv * später mit der Definition von _g_free geladen werden muss. Der Linker verfolgt, dass die Verwendung von _g_free von A von einer späteren Bibliothek erfüllt werden muss. –

Antwort

1

Hier ist das gleiche Problem auf der Kommandozeilenebene mit C. Hier habe ich eine main.c gemacht, die foo() in foo.so aufruft, die bar() in bar.so aufruft, die Aufrufe (zum Spaß) g_free und g_malloc in glib.

$ ls -Flas main.o libfoo.so libbar.so | cut -c3-13,34-37,51- 
-rwxrwxr-x 2976 libbar.so* # has bar(), which calls g_free/g_malloc 
-rwxrwxr-x 3504 libfoo.so* # has foo(), which calls bar() 
-rw-rw-r-- 2864 main.o  # has main(), which calls foo() 

Die richtige Verknüpfung Befehl:

$ gcc -o main main.o -L. -lfoo -lbar -lglib-2.0 
$ LD_LIBRARY_PATH=. ./main 
worked! 

Der Versuch, die Bibliothek Verladeauftrag zu kippen:

$ gcc -o main main.o -L. -lbar -lfoo -lglib-2.0 
./libfoo.so: undefined reference to `bar' 
collect2: error: ld returned 1 exit status 

, die im Wesentlichen das gleiche Problem aufgrund ist Sie sehen. Der entsprechende Abschnitt aus „Mann ld“ ist dies:

Wenn das Archiv ein Symbol definiert, die in einem Objekt nicht definiert wurden , die auf der Kommandozeile vor dem Archiv erschienen, der Linker die entsprechende Datei enthält (s) aus dem Archiv. Ein nicht definiertes Symbol in einem Objekt, das später in der Befehlszeile angezeigt wird, führt jedoch nicht dazu, dass der Linker das Archiv erneut durchsuchen.

So muss man dies beim Laden dynamischer Bibliotheken sogar durch cdll beachten, so scheint es.