2012-10-25 54 views
1

lua/std_vector.i在痛飲2.0.8評論說:如何使用SWIG爲C++ std :: vector生成Lua迭代器?

而對於迭代器不支持&插入/刪除

但也許有人知道如何做到這一點?

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

我已經試過類似的技巧與__call

例如,它可以通過定義__len添加#長度操作符(也可能是偶然的工作,我已經通過試驗和錯誤發現它) ,但我卡住了。 SWIG包裝受阻礙。我嘗試過使用%native,但我無法與%extend一起使用。

回答

0

我不知道該怎麼做,在痛飲模板,但我設法堵塞__call痛飲生成調用luaopen_module後由C的metatable ++:

SWIG_Lua_get_class_metatable(L_, PointVector); 
    SWIG_Lua_add_function(L_, "__call", lua_vector_iterator); 

所以矢量可以作爲迭代器。有點笨拙2合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傳遞指數回下一個時間(在堆棧上第三ARG)迭代。我沒有看到這種行爲記錄,所以我可能依靠實施細節。

這裏是用作__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; 
} 
相關問題