Creating XCode Projects for SWIG Python-bindings

October 24th, 2008 · 1 Comment · Tutorials

SWIG makes the creation of bindings for C/C++ libraries easy for various high-level exits (Java, Perl, PHP, Python, etc.). However, in the case of Python on OS X, when the actual SWIG wrapper is finished the difficulties begin: one needs to create an adequate dynamic library for the Python runtime — and like with everything in life, the devil is in the details. I attempt to provide some helpful instructions on how to create an XCode project for compiling Python modules. The tutorial is based on XCode 2.4.1 and Python 2.5. The instructions may not be valid for newer versions of XCode / Python.

Some preliminary words on the SWIG documentation regarding this topic: there is a general SWIG tutorial featuring instructions on how to create wrappers for some of the most popular exits. In the case of Python there are special instructions on how to build an adequate dynamic library using command-line tools. Unfortunately, these instructions cover the basics, but are a bit misleading sometimes and leave out some important details. The following step-by-step tutorial should fill in the missing stuff.

The following tutorial uses the openFrameworks (0.04) library as an example. However, the process should be very similar for other libraries.

  1. Create the SWIG wrapper for the library you would like to create a Python-binding from. (On OS X you can use fink to install a command-line SWIG tool; instructions on how to build wrappers are available on the SWIG website.)
  2. Ensure both the SWIG wrapper files and the library source code are in the same directory, so you can easily create an XCode project for them.
  3. If there is an XCode project available for the original C/C++-based library, I suggest that you use this project and create a new target for the Python-binding. Otherwise you should first create an XCode project for the actual library and then attach a binding target to it as both the actual source code and the SWIG wrapper need to be compiled.
  4. Create the target by right-clicking on ‘Targets’ and then choose ‘Add’ » ‘New Target…’. Then select ‘BSD’ » ‘Dynamic Library’ as type of the new target:
    Creating the Target
    Finally provide a name for the target. In this case I have named the target ‘ofpython’.
  5. Now it is time to populate the target with source files and linked frameworks. Simply drag and drop the required source files and linked frameworks from the library target and add the SWIG wrapper source files. In the case of openFrameworks this looks like the following:
    Python Target
  6. As you can see I have added the Python.framework to the ofpython target. You must do so as well by right-clicking the target, then choose ‘Add’ » ‘Existing Frameworks…’ and select the Python.framework from ‘/Library/Frameworks’.
  7. Now let’s talk about the tricky part, target configuration. In order to enable Python to load the compiled module, there are a number of modifications that have to be done. The following is a step by step to-do list of each setting that has to be changed:
    1. Change the Product Name to the library name prefixed with an underscore. That is for the openFrameworks project (which is named ‘openframeworks’ internally) the right product name for the binding is ‘_openframeworks’. This ensures the module can be loaded properly (see discussion on ‘ImportError: dynamic module does not define init function’ issue).
    2. Add adequate Library Search Paths and Header Search Paths if necessary.
    3. Change the Mach-O-Type of the target to ‘Bundle’. (This is roughly discussed in the SwigFaqMaxOSXSharedLibraries also.)
    4. A number of settings have to be changed in order to enable correct linkage with the Bundle Mach-O-Type: firstly deactive ZeroLink. Then set Bundle Loader to the Python runtime (usually ‘/usr/bin/python’). Set CurrentLibraryVersion and Compatibility Version to an empty string as it is not supported with Bundle. Activate Perform Single-Object Prelink. Finally set Executable Prefix to an empty string (erase ‘lib’) and change Executable Extension from ‘dylib’ to ’so’.
  8. Build the newly configured target.
  9. Finished.

Testing your Python module is easy as well. Just open up a terminal and change to the build directory of the target. Then launch a python shell and type ‘import mymodulename’. Afterwards all functions / classes from the module should be available in the Python environment.

Tags: ····

1 response so far ↓

  • 1 bartm  Oct 16, 2009 at 3:30 pm

    This was very helpful, thanks. Is there a way to save the settings in step 7 as a template for future xcode projects?

Leave a Comment

© 2009 Tobis Lensing. All rights reserved. Powered by Wordpress — based upon Cutline by Chris Pearson. This page reflects the personal opinion of the author and is in no way linked to institutions the author is working or has worked for. For more information, see the disclaimer.