1

lua/std_vector.iSWIG 2.0.8のコメントでは、次のように述べています。

イテレータと挿入/消去はサポートされていません

しかし、多分誰かがそれを行う方法を知っていますか?

たとえば、#定義することで長さ演算子を追加する__lenことができます (偶然に機能する可能性があります。試行錯誤で見つけました)。

%include "std_vector.i"
%extend std::vector { int __len(void*) { return self->size(); } }
namespace std {
    %template(PointVector) vector<fityk::Point>;
}

で同様のトリックを試しまし__callたが、行き詰まりました。SWIGラッピングが邪魔になる。を使用してみまし%nativeたが、 と連携させることができませんでした%extend

4

1 に答える 1

0

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;
}
于 2012-10-26T22:35:25.260 に答える