我在OS X上并使用Homebrew安装了Gtk + 3软件包。
brew install gtk+3
我可以使用ctypes
模块在Python中加载已安装的库。
$ 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 10aa33210>
>>> 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
。反过来说没有。任何人都可以解释这种行为吗?
答案 0 :(得分:1)
这里出现了与C命令行级别相同的问题。这里,我创建了一个main.c,它调用foo.so中的foo(),它调用bar中的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
这是由于您所看到的基本相同的问题。来自&#34; man ld&#34;的相关部分是这样的:
如果存档定义了某个对象中未定义的符号 在命令行的归档之前出现,链接器将 包括存档中的相应文件。但是,一个 稍后出现在命令行中的对象中的未定义符号将 不要让链接器再次搜索存档。
因此,即使通过cdll加载动态库,也需要牢记这一点。