首页 > 解决方案 > 如何让 SWIG 公开的 C++ 类表现得像 python 中的元组?

问题描述

我有一个非常简单的 C++ 类,它拥有一个 std::vector。我想通过 SWIG 向 python 公开这个类:

arr.hpp:

#include <vector>
class Arr
{
public:
  inline Arr() : _v() { }
  inline void add(double v) { _v.push_back(v); }
  inline double get(unsigned int i) const { return _v[i]; }
  inline const std::vector<double>& getVector() const { return _v; }
private:
  std::vector<double> _v;
};

我:

%module pyarr

%include <std_vector.i>

namespace std {
%template(VectorDouble) vector<double>;
};

%include Arr.hpp
%{
  #include "Arr.hpp"
%}

生成文件:

swig -c++ -python -naturalvar -o arr_wrap.cpp arr.i
g++ -std=c++11 -fpic -shared arr_wrap.cpp -I/usr/include/python3.5m -o _pyarr.so

test_arr.py:

#!/usr/bin/python3

from pyarr import *

a = Arr()
a.add(1.2)
a.add(2.3)
print("v[0]=",a.get(0))
print("v[1]=",a.get(1))
print("v as vector=",a.getVector())
print("v=",a)

当我执行 test_arr.py 脚本时,我得到:

python3 test_arr.py

v[0]= 1.2
v[1]= 2.3
v as vector= (1.2, 2.3)
v= <pyarr.Arr; proxy of <Swig Object of type 'Arr *' at 0x7f6f6fa4bf00> >

我必须做什么才能让我的 Arr 类表现得像一个 python 元组?所以最后一行将是:

v= (1.2, 2.3)

[编辑]:我的问题不仅用于显示目的,还用于绘制直方图或初始化 numpy 数组等...

请注意,按照此处提出的答案(How to use a Python list to assign a std::vector in C++ using SWIG?),我尝试在 swig 命令行中使用和不使用 %naturalvar。

标签: pythonc++vectorswig

解决方案


您可以扩展该类以包含一个__repr__函数,以便 Python 将Arr根据需要显示该类:

更新了 arr.i:

%module pyarr

%{
    #include <string>
    #include <sstream>
    #include "Arr.hpp"
%}

%include <std_vector.i>
%include <std_string.i>

namespace std {
%template(VectorDouble) vector<double>;
};

%extend Arr {
    std::string __repr__()
    {
        std::ostringstream ss;
        auto v = $self->getVector();
        auto size = v.size();
        ss << "(";
        if(size > 0) {
            ss << v[0];
            for(size_t i = 1; i < size; ++i)
                ss << ", " << v[i];
        }
        ss << ")";
        return ss.str();
    }
}

%include "Arr.hpp"

test_arr.py 的输出:

v[0]= 1.2
v[1]= 2.3
v as vector= (1.2, 2.3)
v= (1.2, 2.3)

推荐阅读