如何在Python中将swig矩阵对象转换为字符串
我正在使用 openbabel 的 swig 封装(这个是用 C++ 写的,通过 swig 提供了一个 Python 的接口)。
下面我只是用它来读取一个分子结构文件,并获取它的单位晶胞属性。
import 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> >
单位晶胞有一个叫 CellMatrix() 的函数,
unitcell.GetCellMatrix()
<22> <openbabel.matrix3x3; proxy of <Swig Object of type 'OpenBabel::matrix3x3 *' at 0x17b3ecf0> >
OpenBabel::matrix3x3 大概是这样的:
1 2 3
4 5 6
7 8 9
我想知道怎么打印出这个 matrix3x3 的内容。我试过用 __str__
和 __repr__
。
有没有什么通用的方法可以把用 swig 封装的矩阵内容转成字符串在 Python 中显示出来?
谢谢!
2 个回答
接着@jhoon的回答,SWIG似乎不识别std::string这种返回类型,所以你需要把函数改成返回const char*。另外,因为这个函数是在类外部的,你不能用self,而是要用SWIG的$self变量。
所以,在SWIG的.i文件中,如果你写下以下内容:
%extend OpenBabel::matrix3x3 {
const char* __str__() {
std::ostringstream out;
out << *$self;
return out.str().c_str();
}
};
当你在Python中打印matrix3x3的时候,就应该能得到想要的结果。
如果你发现自己需要在很多类中添加这个,考虑把它封装成一个宏,比如:
%define __STR__()
const char* __str__() {
std::ostringstream out;
out << *$self;
return out.str().c_str();
}
%enddef
然后再用以下方式把它添加到类中:
%extend OpenBabel::matrix3x3 {
__STR__()
};
根据这个openbabel的文档,Python的绑定没有提供一个好方法来打印matrix3x3对象
,是有原因的。matrix3x3
这个C++类重载了<<
运算符,但SWIG会直接忽略这个运算符。
http://openbabel.org/api/2.2.0/classOpenBabel_1_1matrix3x3.shtml
这意味着你需要修改你的SWIG接口文件(可以查看http://www.swig.org/Doc1.3/SWIGPlus.html#SWIGPlus_class_extension),为C++中的openbabel::matrix3x3
添加一个__str__
方法,这个方法会包装<<
运算符。你的方法可能看起来像这样:
std::string __str__() {
//make sure you include sstream in the SWIG interface file
std::ostringstream oss(std::ostringstream::out);
oss << (*this);
return oss.str();
}
我相信在这种情况下,SWIG会正确处理C++的返回类型std::string
,但如果不行,你可能需要尝试返回一个字符数组。
到这一步,你应该能够重新编译绑定,并重新运行你的Python代码。调用str()
在matrix3x3
对象上,现在应该能显示出在C++中用<<
运算符显示的内容。