2009-06-25 3 views
2

Je dois effectuer des opérations sur les tables Lua à partir de C où les tables sont traitées comme des listes ou des files d'attente. Plus précisément, j'ai besoin d'insérer un élément en tête et d'enlever l'élément de tête, et de faire bouger les autres éléments pour accommoder le nouvel élément.Comment faire des opérations de table lua à partir de C?

Ce serait simple en lua droite, j'utiliserais table.insert et table.remove. Mais dans C?

Il y a des fonctions dans le Lua C api tels que lua_settable, mais pas d'équivalent pour table.insert et table.remove qui refait surface. Il semble qu'il y ait des fonctions internes C à l'intérieur de l'interpréteur appelées tinsert et tremove, mais elles ne font pas partie de l'API.

Dois-je vraiment faire appel à une fonction lua qui le fait pour moi?

Répondre

4

Je crois que vous pouvez réutiliser les fonctions

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

et la macro

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

qui sont dans le ltablib.c. Ils dépendent uniquement de l'API de Lua.

+0

merci. Mais quand j'ai essayé tinsert de mon code, il échoue parce que la valeur de retour de lua_gettop n'est pas ce qu'elle attend. Il y a déjà des valeurs sur la pile, donc lua_gettop retourne quelque chose comme 24, et cette fonction attend le nombre d'arguments passés, par exemple 2 ou 3. –

+0

Poussez-vous, par exemple, position et valeur dans la pile avant vous appelez tinsert? –

+0

Oui, la fonction peut être appelée à partir de différents contextes où la pile a déjà des quantités de choses différentes. J'ai donc ajouté une variable supplémentaire à ma version de tinsert pour le décalage de pile et fait que les internes de mon tinsert utilisent ce décalage. Maintenant ça marche. Merci. –

1

Code non testé, mais voici un croquis. Vous passez l'index de la table, et pour la fonction d'insertion, également l'index de la valeur que vous voulez insérer. Pour la suppression, la valeur est poussée sur la pile 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

c'est un joli code propre :) –

Questions connexes