Python ctypes与动态链接

4 投票
2 回答
3997 浏览
提问于 2025-04-15 21:24

我正在用C语言写一些库,这些库里的函数我想通过ctypes从Python调用。

我之前成功地做过一个库,但那个库的依赖关系很简单(主要是 fstreammathmallocstdiostdlib)。而我现在正在做的这个库依赖关系就复杂多了。

举个例子,我想使用 fftw3。作为测试,我会先尝试编译一个简单的 .cpp 文件,内容如下:

int foo()
{
    void *p  = fftw_malloc( sizeof(fftw_complex)*64 );
    fftw_free(p);

    printf("foo called.\n");

    return 0;
}        

我这样编译它:

icpc -Wall -fPIC -c waveprop.cpp -o libwaveprop.o $std_link
icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o 

cp waveprop.so.1.0 /usr/local/lib/
rm waveprop.so.1.0
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so.1

这一切都正常。接下来我用另一个 .cpp 文件进行测试,内容是:

int main()
{
    foo();
}

结果是:

icpc test.cpp -lwaveprop 
/lib/../lib64/libwaveprop.so: undefined reference to `fftw_free'
/lib/../lib64/libwaveprop.so: undefined reference to `fftw_malloc'

这完全合理。接下来我尝试:

icpc test.cpp -lwaveprop -lfftw3
./a.out
foo called.

太好了!但是现在当我尝试用ctypes加载这个库时:

>>> from ctypes import *
>>> print cdll.LoadLibrary('/usr/local/lib/libwaveprop.so.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/ctypes/__init__.py", line 431, in LoadLibrary
    return self._dlltype(name)
  File "/usr/lib64/python2.6/ctypes/__init__.py", line 353, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: /usr/local/lib/libwaveprop.so.1: undefined symbol: fftw_free

所以这是同样的问题,但我不知道如何用ctypes解决它。我尝试了各种方法都没有成功,现在我有点卡住了。

2 个回答

0

你需要把 libwaveprop.so 这个文件和 fftw3 库连接起来。否则,Python 就不知道去哪里找那些缺失的符号;编程语言可没有读心术哦。

4

好的,谢谢你的帮助。

为了让这个正常工作,我在链接的时候必须包含依赖项(真是的)。我之前试过这个,但出现了错误。为了解决这个问题,我需要用'-fpic'这个选项重新编译fftw。现在一切都正常了。

icpc -Wall -fPIC -c waveprop.cpp -o libwaveprop.o $std_link
icpc -shared -Wl,-soname,libwaveprop.so.1 -o libwaveprop.so.1.0 libwaveprop.o -lfftw3

cp waveprop.so.1.0 /usr/local/lib/
rm waveprop.so.1.0
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so
ln -sf /usr/local/lib/waveprop.so.1.0 /usr/local/lib/waveprop.so.1

谢谢,
-nick

撰写回答