std::vectorがどうなっているか

vertices.h

#include <vector>

struct Vertex
{
    float x;
    float y;
    float z;
};

struct Container
{
    std::vector<Vertex> vertices;
};

に対してswigインターフェース
vertices.i

%module vertices
%{
#include "vertices.h"
%}
%include "vertices.h"
%include "std_vector.i"
%template(VertexVector) std::vector<Vertex>;

とした時にVertexVectorがどんな実装になるか。
とりあえず

$ swig -python -c++ vertices.i
$ ls vertices*
vertices.h  vertices.i  vertices.py  vertices_wrap.cxx

vertices.pyのstd::vectorをあらわすclass VertexVectorはfor文に関係あるところだけを抜粋すると

class VertexVector(_object):
    def iterator(self): return _vertices.VertexVector_iterator(self)
    def __iter__(self): return self.iterator()

となっている。
_vertices.VertexVector_iteratorはvertices_wrap.cxxにある。

{ (char *)"VertexVector_iterator", _wrap_VertexVector_iterator, METH_VARARGS, NULL}

と登録されるので実体は_wrap_VertexVector_iterator
なんか良くわからないが、VertexVector::iteratorの返り値はSwigPyIteratorだった。
SwigPyIteratorはvertices.pyに定義されていてforに関係あるところだけだと

class SwigPyIterator(_object):
    def next(self): return _vertices.SwigPyIterator_next(self)
    def __iter__(self): return self

vertices_wrap.cxxでは

{ (char *)"SwigPyIterator_next", _wrap_SwigPyIterator_next, METH_VARARGS, NULL},

と定義されている。
_wrap_SwigPyIterator_nextのソースを追う(抜粋)

SWIGINTERN PyObject *_wrap_SwigPyIterator_next(PyObject *SWIGUNUSEDPARM(self), PyObject *args) 
{
swig::SwigPyIterator *arg1;
PyObject *result;
result = (PyObject *)(arg1)->next();
}
↓
SwigPyIterator::PyObject *next()
{
 PyObject *obj = value();
}
↓
typename ValueType = typename std::iterator_traits<OutIterator>::value_type
PyObject *SwigPyIteratorOpen_T::value() const {
  return from(static_cast<const value_type&>(*(base::current)));
}
↓
template <class Type>
inline PyObject *from(const Type& val) {
  return traits_from<Type>::from(val);
}
↓
template <class Type> struct traits_from {
  static PyObject *from(const Type& val) {
    // コピーコンストラクタを使ってnewしてるのを発見
    return traits_from_ptr<Type>::from(new Type(val), 1);
  }
};

newを回避したら速くなるか試してみる


ポインタが返り値の時はnewが呼ばれないので、
元のクラスに適当にポインタを返す関数を作ったら遅くなるのを回避できるようだ。

struct Container
{
    std::vector<Vertex> vertices;

    Vertex* getVertex(int index){
        return &vertices[index];
    }
};