Compiling a SWIG Python wrapper for a static library?

≡放荡痞女 提交于 2020-01-01 07:20:10

问题


This is a noob question. I'm trying to learn how to use SWIG to make a python interface for a C++ library. The library is a proprietary 3rd party library; it comes to me in the form of a header file (foo.h) and a static archive (libfoo.a).

To simplify matters, I've cooked up an example which I think has the same pathology. Same error messages anyways.

/* foo.hpp */
class TC {
    public:
       TC();
       int i;
    private:
};

For reference, here's foo.c. I only have the header and archive files for the real 3rd party library.

/*foo.cxx */
#include "foo.hpp"
TC::TC() {
    i = 0;
}

I made this library by typing g++ -c foo.cxx && ar rcs libfoo.a foo.o

My SWIG interface file is as follows:

/* foo.i */ 
%module foo
%{
#include "foo.hpp"
%}
%include "foo.hpp"

I generate foo_wrap.cxx by typing

swig -python -c++ foo.i

and then compile.

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

The compilation succeeds, but when I run Python and import foo, I get an undefined symbol error.

>>> 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

What's going on here? The problem seems to be that the linking step isn't finding the definition of the constructor TC::TC.

Note: If I alter the linking step to

g++ -shared -L. -lfoo -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -o _foo.so

then everything works. But is this an option for my real problem, where I don't have the raw source code? Can one extract a .o from a .a? Presumably one can do this by hand, but shouldn't there be some automated way of doing it?


回答1:


I'm not really sure if it's the case for you but in general the order of object files and static libraries matters. The order defines the order of initialisation.

You have to put the most general objects and/or static archives as last parameters. The objects/archives with the most dependencies have to be placed at the beginning.

An example. The object file A.o offer the fucntion A(). The object B.o uses the function A(). You have to write ld -o libmy.so B.o A.o (the most general file A.o as last parameter).

You can also check with objdump -x _foo.so if the symbol exists in the file.

The right call would be: g++ -shared -L. -lpython2.6 -Wl,-soname,_foo.so foo_wrap.o -lfoo -o _foo.so

Do not be confused with -lpython2.6, it's a dynamic library linked at runtime.



来源:https://stackoverflow.com/questions/4608780/compiling-a-swig-python-wrapper-for-a-static-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!