简体   繁体   中英

Compiling a SWIG Python wrapper for a static library?

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?

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 Ao offer the fucntion A(). The object Bo uses the function A(). You have to write ld -o libmy.so Bo Ao (the most general file Ao 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 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM