2009-06-25 2 views
2

Мне нужно выполнить операции над таблицами Lua от C, где таблицы рассматриваются как списки или очереди. В частности, мне нужно вставить элемент в голову и удалить элемент головки, а другие элементы перемещаться для размещения нового элемента.Как выполнить операции lua table с C?

Это было бы просто прямолинейно, я бы использовал table.insert и table.remove. Но в C?

Есть функции в API Lua C, такие как lua_settable, но не эквиваленты table.insert и table.remove, которые всплыли. Похоже, что внутри интерпретатора есть внутренние функции C, но они не являются частью api.

Нужно ли мне звонить в функцию lua, которая делает это для меня?

ответ

4

Я считаю, что вы можете использовать функции

static int tinsert (lua_State *L) 
static int tremove (lua_State *L) 

и макро

#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) 

, которые находятся в ltablib.c. Они зависят только от API Lua.

+0

спасибо. Но когда я попытался использовать мой код, он терпит неудачу, потому что возвращаемое значение lua_gettop не соответствует ожидаемому. В стек уже есть значения, поэтому lua_gettop возвращает что-то вроде 24, и функции ожидают, что это будет количество переданных аргументов, например 2 или 3. –

+0

Вы нажимаете, например, позицию и значение в стеке раньше вы называете tinsert? –

+0

Да, функция может быть вызвана из разных контекстов, где в стек уже много разных вещей. Поэтому я добавил дополнительную переменную в мою версию tinsert для смещения стека и сделал внутренности моего tinsert использовать это смещение. Теперь это работает. Благодарю. –

1

Код не проверен, но вот эскиз. Вы передаете индекс таблицы, а для функции вставки - также индекс значения, которое вы хотите вставить. Для удаления значение нажимается на стек Lua.

#define getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) 

void insert_at_head (lua_State *L, int tbl_idx, int val_idx) { 
    int e; 
    /* shift elements right to make room */ 
    for (e = getn(L, tbl_idx) + 1; e > 1; e--) { 
    lua_rawgeti(L, tbl_idx, e-1); 
    lua_rawseti(L, tbl_idx, e); 
    } 
    lua_pushvalue(L, val_idx); 
    lua_rawseti(L, tbl_idx, 1); 
} 

void remove_from_head_and_push (lua_State *L, int tbl_idx) { 
    int e; 
    int n = getn(L, tbl_idx); 
    if (n == 0) 
    return luaL_error("removed from head of empty list"); 
    lua_rawgeti(L, tbl_idx, 1); /* push first element */ 
    /* shift elements left */ 
    for (e = 2; e < n; e++) 
    lua_rawgeti(L, tbl_idx, e); 
    lua_rawseti(L, tbl_idx, e-1); 
    } 
    lua_pushnil(L, val_idx); 
    lua_rawseti(L, tbl_idx, n); 
} 
+0

это хороший чистый код :) –

Смежные вопросы