How to stringfy a swig matrix object in python
I am using swig wrapper of openbabel (written in C++, and supply a python wrapper through swig)
Below i just use it to read a molecule structure file and get the unitcell property of it.
i开发者_开发问答mport pybel
for molecule in pybel.readfile('pdb','./test.pdb'):
unitcell = molecule.unitcell
print unitcell
|..>
|..>
<openbabel.OBUnitCell; proxy of <Swig Object of type 'OpenBabel::OBUnitCell *' at 0x17b390c0> >
The unitcell has function CellMatrix(),
unitcell.GetCellMatrix()
<22> <openbabel.matrix3x3; proxy of <Swig Object of type 'OpenBabel::matrix3x3 *' at 0x17b3ecf0> >
the OpenBabel::matrix3x3 is something like :
1 2 3
4 5 6
7 8 9
i am wondering how to print out the contents of the matrix3*3 . I have tried __str__
and __repr__
with it.
Any general way to stringfy the contents of a matrix wrapped by swing in python ?
thanks
Based on this openbabel documentation, it looks like there is a good reason the Python bindings don't come with a nice way to print a matrix3x3 object
. The matrix3x3
C++ class overloads the <<
operator, which SWIG will simply ignore:
http://openbabel.org/api/2.2.0/classOpenBabel_1_1matrix3x3.shtml
This means that you'll need to modify your SWIG interface file (look at http://www.swig.org/Doc1.3/SWIGPlus.html#SWIGPlus_class_extension) to add a __str__
method to openbabel::matrix3x3
in C++ which wraps the <<
operator. Your method might look a lot like
std::string __str__() {
//make sure you include sstream in the SWIG interface file
std::ostringstream oss(std::ostringstream::out);
oss << (*this);
return oss.str();
}
I believe that SWIG will properly handle C++ a return type of std::string
in this case, but if not you might have to play around with returning a character array.
At this point, you should be able to recompile the bindings, and rerun your Python code. Calling str()
on a matrix3x3
object should now display what would be displayed with the <<
operator in C++.
Further to the answer from @jhoon, it seems that SWIG doesn't recognise the std::string return type so change the function to return const char*. Also, since it is a function outside the class, you can't use self but you must use SWIG's $self variable.
So, in the SWIG .i file, if you put the following:
%extend OpenBabel::matrix3x3 {
const char* __str__() {
std::ostringstream out;
out << *$self;
return out.str().c_str();
}
};
you should get the desired result when calling Python's print on a matrix3x3.
If you find yourself adding this to many classes, consider wrapping it in a macro like:
%define __STR__()
const char* __str__() {
std::ostringstream out;
out << *$self;
return out.str().c_str();
}
%enddef
and then adding it to the class with:
%extend OpenBabel::matrix3x3 {
__STR__()
};
精彩评论