SWIGテンプレートでそれを行う方法はわかりませんが__call
、呼び出した後、C ++からSWIGで生成されたメタテーブルにプラグインすることができましたluaopen_module
:
SWIG_Lua_get_class_metatable(L_, PointVector);
SWIG_Lua_add_function(L_, "__call", lua_vector_iterator);
そのため、ベクトルを反復子として使用できます。2 in 1 は少し扱いにくいですが、機能します。
> = points
<PointVector userdata: 190FBE8>
> for n, p in points do print(n, p) end
0 (24.0154; 284; 16.8523)
1 (24.0541; 343; 18.5203)
イテレータは Python のようにインデックスと値を返しenumerate()
、Lua は次回イテレータにインデックスを渡します (スタックの 3 番目の引数)。この動作が文書化されているのを見たことがないので、実装の詳細に依存している可能性があります。
として使用される関数は次の__call()
とおりです。
// SWIG-wrapped vector is indexed from 0. Return (n, vec[n]) starting from n=0.
static int lua_vector_iterator(lua_State* L)
{
assert(lua_isuserdata(L,1)); // in SWIG everything is wrapped as userdata
int idx = lua_isnil(L, -1) ? 0 : lua_tonumber(L, -1) + 1;
// no lua_len() in 5.1, let's call size() directly
lua_getfield(L, 1, "size");
lua_pushvalue(L, 1); // arg: vector as userdata
lua_call(L, 1, 1); // call vector<>::size(this)
int size = lua_tonumber(L, -1);
if (idx >= size) {
lua_settop(L, 0);
return 0;
}
lua_settop(L, 1);
lua_pushnumber(L, idx); // index, to be returned
lua_pushvalue(L, -1); // the same index, to access value
lua_gettable(L, 1); // value, to be returned
lua_remove(L, 1);
return 2;
}