为 C 库生成 Python SWIG 绑定时未定义的符号

Posted

技术标签:

【中文标题】为 C 库生成 Python SWIG 绑定时未定义的符号【英文标题】:Undefined symbol when generating Python SWIG binding for C library 【发布时间】:2012-10-08 12:43:57 【问题描述】:

我正在尝试与 Python 中的 mdb 库交互,使用 SWIG 根据 mdb 附带的头文件生成绑定。这是我第一次尝试这样做,最终在 python 中加载共享库时,我遇到了一个未定义的符号。

这是我的接口定义文件:

$ cat pymdb.i
%module pymdb
%
#include "mdbtools.h"
%
%include "mdbtools.h"

生成 C 代码会引发以下警告:

$ swig -python -o pymdb.c -I/usr/include pymdb.i
/usr/include/mdbtools.h:187: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:188: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:189: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:190: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:191: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:192: Warning 451: Setting a const char * variable may leak memory.
/usr/include/mdbtools.h:193: Warning 451: Setting a const char * variable may leak memory.

编译C代码,一切正常:

$ gcc -c -fPIC -I/usr/include/python2.7 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include pymdb.c -o pymdb.o

将其链接到 /usr/lib/x86_64-linux-gnu/libmdb.so.2.0.0 文件(Debian 多架构):

$ ld -shared -lmdb pymdb.o -o _pymdb.so

这是我得到未定义符号的地方,在 python 中加载 .so:

$ echo "import pymdb" |python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pymdb.py", line 26, in <module>
    _pymdb = swig_import_helper()
  File "pymdb.py", line 22, in swig_import_helper
    _mod = imp.load_module('_pymdb', fp, pathname, description)
ImportError: ./_pymdb.so: undefined symbol: read_pg_if_16

在 mdbtools.h 中有一个 read_pg_if_16 的声明:

extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos);

我可以在 _pymdb.so 文件表中看到未定义的符号:

$ objdump -T _pymdb.so |grep read_pg_if_16
0000000000000000      D  *UND*  0000000000000000 read_pg_if_16

但 libmdb.so.2 不提供此符号:

$ objdump -T /usr/lib/x86_64-linux-gnu/libmdb.so.2 |grep read_pg_if_16

会不会是我的接口文件有错误?或者这可能是 libmdb.so.2 的问题,没有暴露这个符号?我对 C 和链接的东西没有那么深入,所以在这一点上我对如何着手解决这个问题有点迷茫。

【问题讨论】:

快速猜测:链接时更改参数的顺序是否可以解决问题?如果有,请参阅***.com/questions/8140494/…。 【参考方案1】:

一个可能性是在头文件中声明了一个函数,但在目标文件中没有定义。这在 C 中可以正常工作,其中包含未引用的声明不是问题,但是当 swig 包装声明时,它将创建一个引用,从而导致共享库无法加载。

【讨论】:

这正是我的问题,删除标头声明修复了未定义符号问题。

以上是关于为 C 库生成 Python SWIG 绑定时未定义的符号的主要内容,如果未能解决你的问题,请参考以下文章

痛饮、python 和 wchar_t 问题

c 的 SWIG python 绑定找不到标准头文件的 _EXFUN

SWIG 不支持 include_next GNU 指令

python/c++接口库比较(SWIG,boost.python, pycxx, py++, sip, Weave, Pyrex )

我们可以使用 SWIG 为 Qt 应用程序制作 python 绑定吗?

使用 SWIG 绑定 Python/C++ 模板