Anuncios

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.

Anuncios

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.

Anuncios

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.

Anuncios
Anuncios

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;
}
Anuncios

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 */
}
Anuncios

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.
Anuncios

Para finalmente declarar una funcion principal usando a luaL_register:

int luaopen_milib(lua_State *L)
{
	luaL_register(L, "milib", milib);
	return 1;
}
Anuncios

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.

Anuncios

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"
Anuncios

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.
Anuncios

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.

Anuncios

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.

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