tags:

views:

237

answers:

2

Hi all

I hit this issue about two years ago when I first implemented our SWIG bindings. As soon as we exposed a large amount of code we got to the point where SWIG would output C++ files so large the compiler could not handle them. The only way I could get around the issue was to split up the interfaces into multiple modules and to compile them separately.

This has several downsides:

• Each module must know about dependencies in other modules. I have a script to generate the interface files which handles this side of things, but it adds extra complexity.

• Each additional module increases the time that the dynamic linker requires to load in the code. I have added an init.py file that imports all the submodules, so that the fact that the code is split up is transparent to the user, but what is always visible is the long load times.

I'm currently reviewing our build scripts / build process and I wanted to see if I could find a solution to this issue that was better than what I have now. Ideally, I'd have one shared library containing all the wrapper code.

Does anyone know how I can acheive this with SWIG? I've seen some custom code written in Ruby for a specific project, where the output is post-processed to make this possible, but when I looked at the feasibility for Python wrappers it does not look so easy.

A: 

If split properly, the modules don't necessarily need to have the same dependencies as the others - just what's necessary to do compilation. If you break things up appropriately, you can have libraries without cyclic dependencies. The issue with using multiple libraries is that by default, SWIG declares its runtime code statically, and as a result, as problems passing objects from one module to another. You need to enable a shared version of the SWIG runtime code.

From the documentation (SWIG web page documentation link is broken):

The runtime functions are private to each SWIG-generated module. That is, the runtime functions are declared with "static" linkage and are visible only to the wrapper functions defined in that module. The only problem with this approach is that when more than one SWIG module is used in the same application, those modules often need to share type information. This is especially true for C++ programs where SWIG must collect and share information about inheritance relationships that cross module boundaries.

Check out that section in your downloaded documentation (section 16.2 The SWIG runtime code), and it'll give you details on how to enable this so that objects can be properly handled when passed from one module to the other.

FWIW, I've not worked with Python SWIG, but have done Tcl SWIG.

Trey Jackson
I think you've missed the point a little bit: I don't have a problem passing things from one module to another, that all works well, care of the "import" statement.The problem is that I want to link multiple modules into one shared library to speed up the load times when importing the code.
jkp
Ah, sorry about that, no solution for speeding it up. With Tcl, we were able to delay loading of modules until they were needed using the package mechanism. This did help speed things up, but as far as just plain speeding up loading - no dice.
Trey Jackson
+3  A: 

OK guys, sharing this for anyone else who ever hits this issue: I found a working solution to the issue here.

Essentially, you need to implement a bit of custom C code that will act as an umbrella init function for your generated modules. In the init function you call the sub-init functions for each embedded module you wish to import, adding the contents to the Python package containing the library and python wrapper code (the accompanying .py files generated by SWIG).

The solution seems to work well, and solves the speed problems I mentioned above. Finally, after two years I have a solution that works like I want it to!

jkp
+1 for doing the work and sharing, thanks. Looks like I had this solved already via Tcl's package mechanism (if understand what you wrote).
Trey Jackson
@Trey Jackson: so you have a way to link several TCL modules into one binary? I'd be interested how you do this as well...we also have TCL SWIG based modules.
jkp