How to stringfy a swig matrix object in python

前端 未结 2 1844
走了就别回头了
走了就别回头了 2021-01-13 22:26

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 unit

相关标签:
2条回答
  • 2021-01-13 23:25

    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++.

    0 讨论(0)
  • 2021-01-13 23:29

    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__()
    };
    
    0 讨论(0)
提交回复
热议问题