Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre el primero de los tres lugares para almacenar datos no locales con la API de C, en este caso el registro.

Anuncios

Este esta siempre ubicado en un pseudo-indice y cuyo valor es definido por LUA_REGISTRYINDEX, un pseudo-indice es como un indice dentro de la pila excepto que su valor asociado no esta en la pila, la mayoria de las funciones en la API de Lua que aceptan indices como argumentos tambien aceptan pseudo-indices, las excepciones son esas funciones que manipulan la pila misma tales como lua_remove y lua_insert, por ejemplo para conseguir un valor almacenado con la clave “key” en el registro se puede usar la siguiente llamada:

lua_getfield(L, LUA_REGISTRYINDEX, "key");
Anuncios
Anuncios

El registro es una tabla comun de Lua, tal como se puede indexarlo con cualquier valor excepto nil, sin embargo porque todos los modulos de C comparten el mismo registro, se deben escoger con cuidado los valores para usar como claves para evitar colisiones, las claves de cadena son particularmente utiles cuando quieres permitir que otras librerias independientes puedan acceder tu informacion porque solo necesitas saber cual es el nombre de la clave, para tales claves no existe un metodo infalible para escoger nombres pero hay otras buenas practicas tales como evitar nombres comunes y prefijar tus nombres con el nombre de la libreria o algo similar, prefijos como lua o lualib no son buenas opciones, otra opcion es utilizar uuid (identificador unico universal por sus siglas en ingles) como la mayoria de los sistemas ahora tienen programas para generar tales identificadores (p.e. uuidgen en Linux), un uuid es un numero de 128 bits, escrito en hexadecimal para formar una cadena alfanumerica, que es generado por una combinacion de la direccion MAC del host, una marca de tiempo, y un componente a la azar asi nos aseguramos que sea diferente de cualquier otro uuid.

Anuncios

Se deberia evitar el uso de numeros como claves en el registro porque tales claves son reservadas para el sistema de referencia, este sistema esta compuesto por un par de funciones en la libreria auxiliar que te permiten almacenar valores en una tabla sin preocuparte sobre como crear nombres unicos, la llamada es:

int r = luaL_ref(L, LUA_REGISTRYINDEX);
Anuncios

Esta quita un valor de la pila, la almacena dentro del registro con una clave numerica de tipo entera nueva y devuelve esta clave, a esta clave la llamamos referencia.

Anuncios
Anuncios

Como implica el nombre la usamos principalmente como referencia cuando necesitamos almacenar una referencia para un valor de Lua dentro de una estructura de C, como vimos anteriormente no deberiamos almacenar nunca apuntadores para cadenas de Lua por fuera de las funciones de C que las recuperan, incluso Lua no ofrece apuntadores a otros objetos, tales como tablas o funciones asi que no podemos referir a objetos de Lua a traves de apuntadores, en su lugar cuando necesitamos de los apuntadores podemos crear una referencia y la almacenamos en C, para empujar el valor asociado con una referencia r en la pila, simplemente escribimos:

lua_rawgeti(L, LUA_REGISTRYINDEX, r);

Por ultimo para liberar tanto el valor como la referencia llamamos a:

luaL_unref(L, LUA_REGISTRYINDEX, r);
Anuncios

Despues de esta llamada una nueva llamada a luaL_ref puede devolver esta referencia de nuevo, el sistema de referencia trata a nil como un caso especial, cuando llamamos a luaL_ref para un valor nil, este no crea una nueva referencia sino en su lugar devuelve la referencia constante LUA_REFNIL, la llamada:

luaL_unref(L, LUA_REGISTRYINDEX, LUA_REFNIL);

No tiene efecto, por lo contrario la siguiente llamada:

luaL_rawgeti(L, LUA_REGISTRYINDEX, LUA_REFNIL);
Anuncios

Esta llamada pulsa un nil como se esperaba, el sistema de referencia tambien define la constante LUA_NOREF la cual es un entero diferente de cualquier referencia valida, este es util porque marca referencias como invalidas, tal como LUA_REFNIL cualquier intento de recuperar LUA_NOREF devuelve nil y cualquier intento de liberarlo no tiene efecto.

Anuncios

Otro metodo infalible para crear clave dentro del registro es usar como clave la direccion de una variable estatica en tu codigo, por ejemplo el linkeador de C asegura que esta clave sea unica entre todas las librerias, para usar esta opcion necesitas la funcion lua_pushlightuserdata la cual empuja en la pila de Lua un valor representando al puntero de C, el siguiente codigo muestra como almacenar y recuperar una cadena del registro usando este metodo:

static const char clave = 'k';

lua_pushlightuserdata(L, (void *)&clave);
lua_pushstring(L, miCad);
lua_settable(L, LUA_REGISTRYINDEX);

lua_pushlightuserdata(L, (void *)&clave);
lua_gettable(L, LUA_REGISTRYINDEX);
miCad = lua_tostring(L, -1);
Anuncios

Primero crearemos una constante con una direccion unica, nuestro primero bloque almacenara una cadena, la primera linea empuja la direccion que creamos antes, luego empujamos el valor para finalmente asignarlo en la tabla, nuestro siguiente bloque recupera la cadena, igual que antes primero empujamos la direccion, luego recuperamos el valor desde la tabla y la ultima linea la convierte en cadena y la almacena en miCad.

Anuncios

En resumen, hoy hemos visto el registro, que es, para que se usa, como se puede usar, como trabaja, y un pequeño ejemplo para ver su funcionamiento, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00