- Sun 25 October 2015
- misc
- Glen Berseth
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). There is a short tutorial on this page 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.
- 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. - 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". - 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
- http://web.mit.edu/svn/src/swig-1.3.25/Examples/python/class/index.html2. http://swig.10945.n7.nabble.com/Wrapping-static-library-in-Linux-td5112.html3. http://www.swig.org/tutorial.html4. http://intermediate-and-advanced-software-carpentry.readthedocs.org/en/latest/c++-wrapping.html