Sunday 25 October 2015

Using SWIG to wrap C++ for Python

Intro


In order to be able to access the C++ code from Python (or other languages) I have wrapped some of the functionality using SWIG ([Simple Wrapper Interface Generator](http://www.swig.org/)). There is a short tutorial on [this page](http://www.swig.org/tutorial.html) which covers some of the basics, however this is not enough. I am going to want to wrap far more complex data types and classes.

Getting started

Starting with some code



 /* File : example.c
  * Created by Glen Berseth
  * Date: Oct 25, 2015
  *
  * */
#include 


/*
 * Word.h
 *
 *  Created on: 2015-10-25
 *      Author: gberseth
 */
#ifndef WORD_H_
#define WORD_H_

#include 

class Word
{
public:
    Word(std::string the_word);
    virtual ~Word();

    virtual void updateWord(std::string word);
    virtual std::string getWord();

private:
    std::string _the_word;
};

#endif /* WORD_H_ */



/*
 * Word.cpp
 *
 *  Created on: 2015-10-25
 *      Author: gberseth
 */
#include "Word.h"

Word::Word(std::string the_word) :
    _the_word(the_word)
{
    // TODO Auto-generated constructor stub
}

Word::~Word() {
    // TODO Auto-generated destructor stub
}

void Word::updateWord(std::string word)
{
    this->_the_word = word;
}

std::string Word::getWord()
{
    return this->_the_word;
}
There are some global methods, some global variables and a class that uses a non C-like class std::string.

Create an Interface File


An interface file is kind of like a header file but to be used specifically by swig. In the file you should include all of the methods/attributes/variables/header file you want to be exported. For example:


/* example.i */
%module example
 %{
 /* Put header files here or function declarations like below */
 #include "example.h"
 #include "Word.h"
 %}

 %include "std_string.i" 
 %include "example.h"
 %include "Word.h" 
Note: to be able to use std::string properly you need to include the interface file for the class (std_string.i).

This interface file includes both the header files for the methods and class(es) I want to be able to use in Python.

Generating and Compiling


I found this part to be the most confusing and difficult. SWIG can generate a enormous wrapper file that is almost unreadable and then you need to compile it. The errors you get from this process may not seem simple.

  1. First generate the wrapper code

    swig3.0 -c++ -python example.i
    

    Note: The **-c++** help because it tells SWIG what language is being wrapped, I think it might be C be default. 
  2. Compile the code

    g++ -fpic -c example.h example_wrap.cxx Word.cpp -I/usr/include/python2.7/
    

    You need to add the include directory to that the compilation can find "Python.h". 
  3. Link and Build
    
    gcc -shared example_wrap.o Word.o -o _example.so -lstdc++
    
Linking gave me a rather difficult time. I was getting **ImportError: ImportError:  undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE** errors in python when importing the library. This turned out to be caused by not including the stdc++ link file linking. After adding that link everthing works very nicely.

Use in Python


Using the library in python not might needs be so straightforward. In a more customary Python manner the first argument to a class method is the class object itself. This method is done manually in when using the generated Python code.


Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import _example
>>> _example.new_Word("meat")
>>> w = _example.new_Word("meat")
>>> _example.Word_getWord(w)
'meat'
>>> _example.Word_updateWord(w,"beef")
>>> _example.Word_getWord(w)
'beef'
>>> 


References 

 1. http://web.mit.edu/svn/src/swig-1.3.25/Examples/python/class/index.html
 2. http://swig.10945.n7.nabble.com/Wrapping-static-library-in-Linux-td5112.html
 3. http://www.swig.org/tutorial.html
 4. http://intermediate-and-advanced-software-carpentry.readthedocs.org/en/latest/c++-wrapping.html

Wednesday 21 October 2015

Animation/Simulation System flow of control

Simulation for animation is no easy task. There are many steps when constructing an animation and figuring out when particular data should be instantiated can be tricky. I am going to go over one method I have been using to help organize the steps and structure that could be used to construct the simulation flow of control.




This is for a Simulation Engine that I have been using in my work.

The main steps in the Simulation engine
  1. init() (allocating libraries and structures)
    1. Create empty data structures
    2. Create spatial database
    3. Create planning domain
    4. Modules::init()
      1. Initialize any modules that are going to be used in the simulation
    1. At this point the libraries the user specified are loaded and some global structures are created. Some examples of global structures are the spatial database and the pathPlanning envirionment.
  2. initializeSimulation()
    1. Fill the global data structures
    2. Add all the obstacles to the simulation (All Static geometry and items)
      1. Must be in place before agents are reset/initialized.
  3. preprocessSimulation()
    1. Preconditions
      1. All obstacles should be loaded into the environment
    2. Preprocess all modules
    3. refresh the planning domain
    4. add agents to simulation 
    5. The simulation should be completely setup and ready for simulation.
  4. preprocessFrame()
    1. Store simulation data
    2. Maybe you want to collect some data on the performance of the simulation
  5. update()
    1. Step all of the modules in the system
  6. postprocessFrame()
    1. Update metrics from preprocessFrame
    2. Maybe save a picture or continue creating video
  7. postprocessSimulation()
    1. Collect data of metrics for simulation
    2. Do not remove or clear data yet. 
    3. Maybe write out data to file.
    4. This function is the best time to perform any kind of processing over data collected from the simulation.
  8. cleanupSimulation()
    1. Now data allocated data for the scenario can be reclaimed
    2. Here is when the data structures can be emptied and delete before now that any data collected from the simulation has been processed.
  9. finish()
    1. Now simulation components can be deleted because no more simulation will be done.

I find this separation of allocating objects and data structures and creation of items that go in the data structures very helpful. In helps avoid accidentally accessing data structures before they are done being created. It also helps define the ordering in which types of objects should be added to the simulation. As with any software you never really know what is going to be done with it in the future and I think this structure covers many unseen possibilities.