2016-05-31 5 views
4

OS X을 사용 중이며 Homebrew와 함께 Gtk + 3 패키지를 설치했습니다.동적 라이브러리가로드되는 순서가 중요합니까?

brew install gtk+3 

은 내가 ctypes 모듈 파이썬에서 설치 라이브러리를로드 할 수 있습니다.

$ 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 

지금까지 그렇게 좋았습니다. 한 가지 저를 괴롭히는 것은 위의 두 라이브러리를 로드하려고 시도했지만 다른 순서로 심볼을 찾지 못하면 예외가 발생합니다.

$ 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 

그래서,로드 atk 먼저, 다음 glib, 작동합니다. 주위에있는 다른 방법은 그렇지 않습니다. 아무도이 동작을 설명 할 수 있습니까?

+1

예, C 라이브러리는 순서 종속적이며 의존성은 나중에 의존성보다 시퀀스에 있습니다. C에서 (예를 들어) libs A B와 C를 사용하면 A에서 사용 된 기호 중 C에서 발견 된 것으로 간주되는 기호가 B에서 처음에 이름이 바뀐 interloper에 의해 마스크 처리됩니다. B C A로 주문하면 고장납니다. 여기서 libatk는 A이고 심볼은 _g_free이고 glib *는 나중에 _g_free 정의로 나중에로드해야합니다. 링커는 A의 _g_free 사용이 이후 라이브러리에서 만족해야한다고 추적합니다. –

답변

1

여기 C에서 명령 줄 수준과 동일한 문제가 나타납니다. foo.so에서 foo()를 호출하는 main.c를 작성했습니다.이 bar는 bar.so에서 bar()를 호출합니다. 재미를 위해) glib에 g_free와 g_malloc.

$ 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() 

올바른 연결 명령 : 라이브러리 로딩 순서를 반전하려고

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

: 당신이보고있는 본질적으로 같은 문제로 인해

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

. "남자 LD"에서 관련 부분은 이것이다 : 아카이브 명령 행에서 아카이브 이전에 나타난 어떤 오브젝트 에서 정의되지 않은 심벌을 정의

경우, 링커가 이 (해당 파일이 포함됩니다의)을 아카이브에서 가져옵니다. 그러나 나중에 명령 행에 나타나는 객체에서 정의되지 않은 심볼은 으로 아카이브를 다시 검색하지 않습니다.

그래서 cdll을 통해 동적 라이브러리를로드 할 때이를 염두에 두어야합니다.