I am attempting to create python bindings for some C++ code using swig. I seem have run into a problem trying to create python properties from some accessor functions I have for
There is an easy way to make python properties from methods with swig.
Suppose C++ code Example.h:
C++ header
class Example{
public:
void SetX(int x);
int GetX() const;
};
Lets convert this setter and getter to python propery 'x'. The trick is in .i file. We add some "swiggy" inline python code (with %pythoncode) that is inserted in a body of a resulting python class (in the auto-generated python code).
Swig wrapping Example.i
%module example
%{
#include "example.h"
%}
class Example{
public:
void SetX(int x);
int GetX() const;
%pythoncode %{
__swig_getmethods__["x"] = GetX
__swig_setmethods__["x"] = SetX
if _newclass: x = property(GetX, SetX)
%}
};
Check the python code:
python test code
import example
test = example.Example()
test.x = 5
print "Ha ha ha! It works! X = ", repr(test.x)
That is it!
There is no need to rewrite a class definition. Thanks to Joshua advice, one could use SWIG directive %extend ClassName { }.
Swig wrapping Example.i
%module example
%{
#include "example.h"
%}
%extend Example{
%pythoncode %{
__swig_getmethods__["x"] = GetX
__swig_setmethods__["x"] = SetX
if _newclass: x = property(GetX, SetX)
%}
};
As one may see, test.GetX() and test.SetX() are still in place after conversion. One can hide them by:
a) Rename functions by using %rename, add '_' in the beginning thus making methods "private" for python. In the a SWIG interface .i Example.i
...
class Example{
%rename(_SetX) SetX(int);
%rename(_GetX) GetX();
...
(%rename may be placed in some separated place to save the possibility to convert this class to other languages, which don't need these '_')
b) or one can play with %feature("shadow")
Why do we have to use such things to convert methods to a property by using SWIG? As it was said, SWIG selfishly overrides _setattr_, so one have to use _swig_getmethods_ and _swig_setmethods_ to register functions and stay in the swig way.
The methods listed above, especially with PropertyVoodoo are... It is like burning the house to fry an egg. Also it breaks the classes layout, as one have to create inherited classes to make python properties from C++ methods. I mean if class Cow returns class Milk and the inherited class is MilkWithProperties(Milk), how to make Cow to produce MilkWithProperties?
This approach allows one to:
Update In a newer version SWIG abandoned _swig_property so just use property. It works with old version of swig the same. I've changed the post.