Bienvenidos sean a este post, cuando hablamos de un modulo de C no es otra cosa que un chunk que define varias funciones de Lua y las almacena en lugares apropiados, usualmente como entradas en una tabla.
Un modulo de C para Lua imita esta conducta, ademas de la definicion de la funcion de C tambien debe definir una funcion especial que corresponde al chunk principal de una libreria de Lua, esta funcion deberia registrar todas las funciones de C del modulo y almacenarlas en lugares apropiados asi como el chunk principal de Lua deberia tambien inicializar cualquier otra cosa que se necesite iniciar en este modulo.
Lua percibe a las funciones de C atraves de este proceso de registracion, una vez que una funcion de C es representada y almacenada en Lua este la llama a traves de una referencia directa a su direccion (la cual es la que le dimos a Lua en el momento de registrarla), en otras palabras Lua no depende de un nombre de funcion, ubicacion de paquete o reglas de visibilidad para llamar a una funcion una vez registrada, usualmente un modulo de C tiene una unica funcion publica (externa) la cual es la encargada de abrir la libreria, todas las demas pueden ser privadas y declaradas como estaticas en C.
Cuando extendemos a Lua con funciones de C es una buena idea diseñar tu codigo como un modulo de C, incluso aunque se registre una sola funcion de C porque usualmente mas tarde o mas temprano (siempre es mas temprano) vamos a necesitar agregar mas funciones, para este caso la libreria auxiliar nos proporciona una funcion muy util para hacer este trabajo, la funcion luaL_register toma una lista de funciones de C con sus respectivos nombres y los registra dentro de una tabla con el nombre de la libreria, para el siguiente ejemplo vamos a suponer que queremos crear una libreria con la funcion l_dir que definimos en el post anterior, como primer paso debemos definir la funcion de la libreria:
static int l_dir(lua_State *L)
{
DIR *dir;
struct dirent *entrada;
int i;
const char *path = luaL_checksring(L, 1);
dir = opendir(path);
if (dir == NULL)
{
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
return 2;
}
lua_newtable(L);
i = 1;
while((entrada = readdir(dir)) != NULL)
{
lua_pushnumber(L, i++);
lua_pushstring(L, entrada->d_name);
lua_settable(L, -3);
}
closedir(dir);
return 1;
}
Luego declararemos un array con todas las funciones en el modulo con sus respectivos nombres, este array posee elementos del tipo lua_Reg la cual es una estructura con dos campos, una cadena y un apuntador de funcion:
static const struct luaL_reg milib[] = {
{"dir", l_dir}.
{NULL, NULL} /* es un centinela */
}
En este caso tenemos una sola funcion que declarar (l_dir), si hubiera mas deberian agregarse como se agrego a nuestra funcion.
Nota: La ultima linea de la estructura siempre debe agregarse asi porque es la que indica el final de la misma.
Para finalmente declarar una funcion principal usando a luaL_register:
int luaopen_milib(lua_State *L)
{
luaL_register(L, "milib", milib);
return 1;
}
La llamada a luaL_register crea (o mejor dicho reusa) una tabla con el nombre informado (“milib”) y lo llena con los pares nombre-funcion especificados con el array milib, cuando regresa luaL_register deja en la pila la tabla donde abrio la libreria, la funcion termina devolviendo uno para regresar este valor para Lua.
Despues de finalizada la libreria debemos linkearla con el interprete, la forma mas conveniente para hacerlo con la aplicacion de linkeo dinamico, si tu interprete soporta esta aplicacion, en este caso debes crear una libreria dinamica con tu codigo (milib.dll para Windows, milib.so para Unix) y ubicarlo en alguna parte del path de C, despues de estos pasos puedes podremos cargar nuestra libreria directamente desde Lua con require:
require "milib"
Esta llamada linkeara nuestra libreria milib con Lua, encuentra la funcion luaopen_milib, la registra como una funcion de C y la llama, abriendo el modulo.
Nota: Esta conducta explica porque luaopen_milib debe tener el mismo prototipo que cualquier otra funcion de C.
Si tu interprete no soporta linkeo dinamico, tendras que recompilar Lua con tu nueva libreria, ademas de la recompilacion necesitaras una forma de decirle a interprete que deberia abrir la nueva libreria cuando abra un nuevo estado, una manera simple es agregando a luaopen_milib dentro de la lista de librerias estandar para ser abiertas por lua_openlibs en el archivo linit.c.
En resumen, hoy hemos visto modulos de C, que son, como se contruyen, para que se usan, alguna aplicacion practica, como se pueden compilar, ya sea cuando el interprete permite linkeo dinamico y cuando no, 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.
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