这是一个菜鸟问题。我正在尝试学习如何使用SWIG为C ++库创建python接口。该图书馆是专有的第三方图书馆;它以头文件(foo.h)和静态存档(libfoo.a)的形式出现在我面前。
为简化问题,我已经制作了一个我认为具有相同病态的例子。同样的错误信息。
/* foo.hpp */
class TC {
public:
TC();
int i;
private:
};
供参考,这是foo.c.我只有真正的第三方库的头文件和存档文件。
/*foo.cxx */
#include "foo.hpp"
TC::TC() {
i = 0;
}
我通过输入g++ -c foo.cxx && ar rcs libfoo.a foo.o
我的SWIG界面文件如下:
/* foo.i */
%module foo
%{
#include "foo.hpp"
%}
%include "foo.hpp"
我输入
生成foo_wrap.cxxswig -python -c++ foo.i
然后编译。
g++ -c -fPIC -I/usr/include/python2.6 foo_wrap.cxx
g++ -shared -L. -lfoo -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -o _foo.so
编译成功,但是当我运行Python和import foo
时,我得到一个未定义的符号错误。
>>> import foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo.py", line 25, in <module>
_foo = swig_import_helper()
File "foo.py", line 21, in swig_import_helper
_mod = imp.load_module('_foo', fp, pathname, description)
ImportError: ./_foo.so: undefined symbol: _ZN2TCC1Ev
这里发生了什么?问题似乎是链接步骤没有找到构造函数TC :: TC的定义。
注意:如果我将链接步骤改为
g++ -shared -L. -lfoo -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -o _foo.so
然后一切正常。但这是我真正的问题的一个选项,我没有原始的源代码?可以从.a中提取.o吗?大概是人们可以手工完成这个,但是不应该有一些自动化的方法吗?
答案 0 :(得分:6)
我不确定你是否属于这种情况,但一般情况下,目标文件和静态库的顺序很重要。该订单定义了初始化的顺序。
您必须将最常用的对象和/或静态存档作为最后的参数。必须将具有最多依赖性的对象/存档放在开头。
一个例子。目标文件A.o提供功能A()。对象B.o使用函数A()。您必须编写ld -o libmy.so B.o A.o
(最常用的文件A.o作为最后一个参数)。
如果文件中存在符号,您也可以与objdump -x _foo.so
核对。
正确的电话会是:g++ -shared -L. -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -lfoo -o _foo.so
不要与-lpython2.6混淆,它是运行时的动态库链接。