Iniciar Sesion

Planet

Paso parámetros entre Lua y C++ : Variables globales

Como os prometí hace unos días os he preparado un pequeño tutorial de como integrar Lua en C\C++ y pasar argumentos entre ambos.Bien lo primero que tenéis que hacer el instalar Lua en vuestro sistema. Una vez hecho esto y si habeis configurado vuestro entorno de desarrollo lo mejor es probar si lo habies hecho bien y para ello os recomiendo que hagais una prueba compilando el siguiente codigo:extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"}int main(){ lua_State *LS = lua_open(); luaL_dofile(LS,"hello_name.lua"); lua_close(LS);}En el que como podeis ver importamos todas las cabeceras de la API de Lua y a continuación se crea un puntero a una estructura lua_State que sirve como base para cuaquier otra función con la que queramos trabajar. Después se abre el interprete, ejecutamos un script (que tan solo sacara por pantalla un hola mundo) y cerramos nuevamente el interprete.Como podeís ver es un proces bastante simple, pero, ¿y si queremos que los scripts que tenemos en Lua se comuniquen con la aplicación y\o viceversa? Para ello la API dispone de varias funciones que agilizan estas tareas. En primer lugar y la forma más rapida y sencilla es por medio de variables globales que generamos en nuestra aplicación y que luego utiliza el script en Lua y cuyo contenido puede ser accedido tanto en el script como en la aplicación. Un ejemplo de ello sería el siguiente:int main(){ lua_State *L = lua_open(); // Establecemos la variable global "name" y le asiganmos un valor lua_setglobal(L, "name"); lua_pushstring(L, "Project Infnat"); luaL_dofile(L,"hello_name.lua"); lua_close(L);}Para usar esta variable en el script deberemos saber que el script requiere de ella ya que para su utilización se accede a una variable con el mismo nombre que la que se a creado en el codigfo en C. Un sript en Lua que hace uso de esta sería:io.write("Hello ", name,"\n")Si, solo esta linea. En caso de querer modificar esta variable en el script y obtener los resultado suponiendo que se alamacenaran en esa variable tan solo tenemos que hacer una llamada a la función lua_getglobal como en el ejemplo:lua_getglobal(L, "name");string ret_name = "";if (lua_isstring(L, -1)) { ret_name = lua_tostring(L, -1)); printf(ret_name.c_str());}Donde -1 es el orden de llamada a la variable con la funcion lua_getglobal(...) y tal y como podeis ver en la API en el caso de los diferentes tipos de variables llamariamos a diferentes funciones segun el tipo.

El Makefile

Ya tenemos el entorno de desarrollo preparado para poder compilar Wii Pang, pero, ¿y si a alguien se le ocurre la idea de crear su propio proyecto? Tenemos las herramientas listas, pero para allanar el camino un poco, voy a explicar los “intríngulis” del archivo Makefile, para que sea más sencillo comprenderlo y aplicarlo a nuevos proyectos. Voy a desgranarlo, intentando dar una explicación clara de cada una de las partes.
Debo decir antes de empezar que, tal y como está el Makefile de Wii Pang, es totalmente reutilizable para cualquier nuevo proyecto que se quiera comenzar.
Bueno, al lío:
Comenzamos encontrándonos esto:
# Información sobre bibliotecas externas
LOCALLIBS = screenlib freetype tinyxml
LIBS = -lasnd -lmad -lwiiuse -lbte -lfat -ltinyxml -lfreetype -lscreen -logc -lm
EXTRA = -I$(CURDIR)/freetype/include

Son tres variables, cada una de las cuales almacena información sobre bibliotecas externas que utiliza el proyecto. LOCALLIBS guarda una lista de nombres de bibliotecas cuyo código fuente lo tenemos almacenado en local, y más concretamente, guarda los directorios en los cuales se encuentran los fuentes y las cabeceras de dichas bibliotecas (directorios que deben ser descendientes directos de donde se encuentra el Makefile). LIBS guarda una lista de bibliotecas que se enlazan dinámicamente con la aplicación, y en la cual hay que tener cuidado con el orden, ya que las que tengan dependencia de otra, deben colocarse a la derecha de la cual dependan. Por último, la variable EXTRA está ahí por si, en algún caso, las cabeceras no se encuentran en el mismo directorio que los fuentes de la biblioteca (como ocurre con el caso de la FreeType2).
A continuación, hago una rápida pasada: PROJECT es el nombre del proyecto, TARGET será el nombre del ejecutable, BUILD el nombre del directorio donde queremos que se coloquen los ficheros objeto del proyecto, SOURCE es el directorio donde están los fuentes de nuestro proyecto, y DEPSDIR es el directorio donde se colocarán los archivos de dependencias (extensión .d):
# Nombre del ejecutable y directorios fuente y objeto
PROJECT = Wii Pang
TARGET = boot
BUILD = build
SOURCE = source
DEPSDIR = $(BUILD)

Con estas dos instrucciones, se eliminan las reglas implícitas que pueda haber declaradas, y cargamos las reglas básicas de compilación para Wii:
# Limpiar las reglas implícitas
.SUFFIXES:
# Incluir las reglas básicas para Wii
include $(DEVKITPPC)/wii_rules

Aquí se generan tres listas, a saber: CPPFILES es una lista de archivos con extensión .cpp (todos los archivos fuente de nuestro proyecto que se encuentren en el directorio SOURCE); la lista OFILES, que es la misma que CPPFILES, pero cambiando la extensión de los archivos a .o; y por último, la lista OBJS, que son los archivos de la lista OFILES pero con una ruta absoluta en la que se incluye el directorio BUILD:
# Generar una lista con todos los ficheros objeto del proyecto
CPPFILES = $(notdir $(wildcard $(SOURCE)/*.cpp))
OFILES = $(CPPFILES:.cpp=.o)
OBJS = $(addprefix $(CURDIR)/$(BUILD)/,$(OFILES))

En esta sección, entramos ya en temas menos simplones. INCLUDE es una lista de directorios (con ruta absoluta) donde se encuentran archivos de cabecera que se incluyen en el proyecto, a saber: todos los directorios que hay en la variable LOCALLIBS, las cabeceras de LibOgc y el contenido de la variable EXTRA que definimos antes. Se emplea la notación -Idirectorio.
LIBPATHS es una lista parecida a INCLUDE, pero en la que se guardan los directorios donde se encuentran las bibliotecas de enlace dinámico. Se utiliza la notación -Ldirectorio.
En la variable VPATH se incluye el directorio SOURCE y los directorios incluidos en LOCALLIBS. Por otro lado, OUTPUT es la ruta absoluta hasta el ejecutable que se genera al compilar, y LD es una variable en la cual indicamos el enlazador que utilizamos, en este caso, CXX (realmente, es el powerpc-eabi-g++, y viene definido en el fichero de reglas base_rules; quien quiera echarle un vistazo, puede verlo en la carpeta /opt/devkitpro/devkitpcc, si siguió la guía de instalación de la entrada anterior):
# Variables para la compilación
INCLUDE = $(foreach dir,$(LOCALLIBS),-I$(CURDIR)/$(dir)) -I$(CURDIR)/$(BUILD) -I$(LIBOGC_INC) $(EXTRA)
LIBPATHS = -L$(LIBOGC_LIB) -L$(CURDIR)/$(BUILD)
VPATH = $(CURDIR)/$(SOURCE)$(foreach dir,$(LOCALLIBS),:$(CURDIR)/$(dir))
OUTPUT = $(CURDIR)/$(TARGET)
LD = $(CXX)

No me voy a detener en estos flags de compilación, sólo comentar que si queremos activar la optimización del compilador, o las opciones de debug (ahora mismo, no se les podría dar uso), en CFLAGS es donde hay que poner los parámetros correspondientes:
# Flags para la compilación
CFLAGS = -g -ansi -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
OPTIONS = -MMD -MP -MF
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map

Ahora pasamos a los objetivos del Makefile:
all: directorio libs $(OUTPUT).dol listo
No necesita explicación, este objetivo por defecto llama a esos otros objetivos, que se explican a continuación:
Primero, crear el directorio indicado en BUILD para que almacene los ficheros objeto, las bibliotecas .a, los archivos de dependencias .d, etc:
directorio:
@[ -d $(BUILD) ] || mkdir -p $(BUILD)

Segundo paso, compilar cada biblioteca que tengamos en local (e incluida en la variable LOCALLIBS). Después de quitarle la decoración (los echo), la cosa queda en que se entra en cada directorio que haya en LOCALLIBS, se ejecuta el makefile que haya dentro, y la biblioteca .a resultante se mueve al directorio BUILD:
libs: $(LOCALLIBS)
@echo
@echo Compilando $(PROJECT) ...
$(LOCALLIBS):
@echo
@echo Compilando $@ ...
@$(MAKE) --no-print-directory --silent -C $@
@mv $@/*.a $(CURDIR)/$(BUILD)
@echo $@ ... OK!

Una vez compiladas todas las bibliotecas externas, procedemos a compilar todos los ficheros fuentes que haya en la carpeta SOURCE, y los ficheros objeto resultantes los ponemos en la carpeta BUILD, junto a sus archivos de dependencias .d y a las bibliotecas .a que aún están calientes, recién sacadas del horno:
$(CURDIR)/$(BUILD)/%.o: $(CURDIR)/$(SOURCE)/%.cpp
@echo $(notdir $<)
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)

El último objetivo que se ejecuta desde all es el siguiente, y sirve para limpiar algunos archivos temporales:
listo:
@$(RM) $(CURDIR)/$(SOURCE)/-g $(OUTPUT).elf.map
@echo
@echo $(PROJECT) ... OK!

Otros dos objetivos del Makefile son el típico clean, que se encarga de eliminar el directorio BUILD, y ejecutar la orden make clean en el directorio de cada una de las bibliotecas externas que tenemos en local; y el objetivo run, que se encarga de enviar (a través de la utilidad Wiiload) a nuestra blanquita de Nintendo el archivo ejecutable que hemos generado para que podamos comprobar si todo ha ido bien.
run:
wiiload $(TARGET).dol
clean:
@for dir in $(LOCALLIBS); do $(MAKE) clean --no-print-directory -C $$dir; echo Limpiando $$dir ... OK! ; done
@$(RM) -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol *~ $(SOURCE)/*~
@echo Limpiando $(PROJECT) ... OK!

Estos dos últimos objetivos son para generar los ejecutables (un .elf y un .dol) de nuestro proyecto, y que enlazan el contenido del directorio BUILD haciendo uso de reglas implícitas declaradas en /opt/devkitpro/devkitppc/wii_rules:
DEPENDS := $(OBJS:.o=.d)
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OBJS)
-include $(DEPENDS)

Y eso es todo, el Makefile explicado paso a paso.
Cosas a tener en cuenta: en primer lugar, asumo que se tienen previos conocimientos (medianamente avanzados) de cómo funciona internamente un Makefile, por eso no me paro a detallar cómo funciona cada instrucción/regla/objetivo.
Otro detalles importante: hay a quien le gusta que se vean las instrucciones que se van ejecutando en la salida estándar a medida que el Makefile va ejecutándose; a mí no, así que lo he decorado para que sólo se reflejen mensajes muy sencillitos que indican el progreso de la compilación.
Y por último. Este Makefile es totalmente reutilizable, ya que sólo se necesita indicarle el directorio de fuentes del proyecto, las bibliotecas locales que tenemos (eso sí, éstas deben tener su propio Makefile en su directorio), y poco más. Dentro de un tiempo, cuando tenga más perfilada mi biblioteca, colgaré en la Forja del proyecto lo que sería una plantilla básica de proyecto, con su Makefile, la carpeta de fuentes con un main.cpp sencillito de ejemplo, y la susodicha biblioteca que me estoy currando en su directorio en local; todo ello listo para ser compilado.
Para eso, aún queda, así que sólo quiero agradecer la lectura (si has llegado hasta aquí abajo sin saltarte nada, es que tienes ganas de aprender, jaja), y comunicar que la siguiente entrada estará referida a los detalles que hay que tener en cuenta para programar en Wii: alineamiento de la memoria, padding, caché…
Pero no os asustéis, todo a su tiempo =P
PD: Parece que las etiquetas code no funcionan bien, y se comen el sangrado del código, así que, para que esta entrada sea más ilustrativa, es recomendable tener el propio archivo Makefile por delante en nuestro editor favorito (está en la Forja del proyecto).

Brief description

Here you can find attached a brief description of the project in Spanish. On the website you will find another one in English.

La AEMET abre sus datos

Copiado directamente de la web de la AEMET: (http://www.aemet.es/)
La Agencia Estatal de Meteorología (AEMET) facilita de forma progresiva el acceso libre y gratuito a todos sus datos mediante vía electrónica a partir de hoy, 30 de noviembre.
AEMET adopta así una nueva política de datos que tiene en cuenta de este modo la importancia de la información meteorológica como elemento clave de apoyo a la sociedad y su papel dinamizador tanto de la I+D como de muchas actividades ligadas a la meteorología. Por otra parte, este nuevo enfoque está de acuerdo con las directrices europeas y españolas en materia de información medioambiental.
El acceso a la información gratuita se lleva a cabo por medios electrónicos. La página web incrementa de forma notable sus contenidos de datos de observación (http://www.aemet.es/es/eltiempo/observacion/ultimosdatos) al tiempo que se pone en operación un servidor de ficheros (ftp://ftpdatos.aemet.es) al que se accede tanto directamente como a través del enlace “Servidor de datos” de la propia página web y en el que, en una primera fase, se tiene disponible lo siguiente:
- Datos diezminutales de unas 250 estaciones de observación de las redes de superficie de AEMET.
- Resúmenes diarios de más de 600 estaciones de observación de las redes de superficie de AEMET.
- Datos horarios de radiación solar de la red de medida de AEMET.
- Datos diarios de ozono total y sondeos semanales de ozono.
- Datos diezminutales de las redes de radares y de detección de rayos a intervalos de quince minutos.
- Salidas numéricas del modelo numérico de predicción HIRLAM-AEMET actualizadas cuatro veces al día (mas de 1000 campos por salida).
- Series completas de resúmenes diarios y mensuales de unas 110 estaciones climatológicas seleccionadas con, al menos, 15 años de antigüedad.
- Boletines codificados de observatorios españoles de intercambio internacional.
Por otra parte, a lo largo de 2011, se ampliarán los contenidos de los conjuntos de datos anteriores y se incorporarán nuevos datos y productos.
En definitiva una noticia magnífica para nosotros ya que nos abre la posibilidad de integrar los datos recogidos por la sonda con los obtenidos en las distintas estaciones terrestres cercanas.

Estructura Básica del nucleo de Vidali

Para tratar de comprender un poco la estructura del código de Vidali, he realizado un pequeño esquema de como sería “en teoría” el núcleo de Vidali, donde se detalla las dependendencias entre clases, las funciones de cada clase, y para que se usa en general.
De momento este es un esquema “boceto”, es decir, muestra parte de la estructura actual y aun esá sujeta a cambios.
Saludos!

Seguimos trabajando en el desarrollo

Aunque ahora no estemos a pleno rendimiento con la aplicación, seguimos trabajando en el desarrollo de la misma.
Es una época difícil para nosotros ya que tenemos ahora bastantes exámenes y no nos quedan muchos huecos libres para continuar con el proyecto. Pronto nos pondremos al 100% para adelantar el trabajo. No sabemos cuándo saldrán a la luz nuevas modificaciones pero esperamos no demorarnos mucho y no dejar de lado el proyecto.
Cuando terminemos los exámenes y podamos dedicarnos a esto, nos marcaremos los objetivos a alcanzar para la versión 0.0.2 de la aplicación que puede que ya incluya otro lenguaje de programación. Una vez fijemos objetivos, os informaremos de las novedades.

Mensaje de mantenimiento y noticias

Estoy haciendo pruebas de funcionamiento del RSS, que parece que no funciona del todo bien.
Por cierto que creo que dentro de muy poco podré ponerme de nuevo a tope con el programa, y es muy probable que antes de final de año pueda sacar la primera versión.

Reglas

A continuación os presento las reglas de reconocimiento que generará Infant de cada una de las categorías del árbol de conocimiento:

  • Existe punto (se genera siempre)
    • Comprueba si un determinado punto existe en la estructura que se compara.
    • El sicript tendra tantos "existe puntos" como puntos comunes (+- 10% distancia) entre todos los objetos en la categoria.
  • Existe nivel (se genera siempre)
    • Este tipo de comprobacion se creara si todos los objetos de una misma categoria tienen niveles similares y en el mismo orden.
    • En siguientes versiones además se definirá la relación que existe entre los diferentes niveles (como diferencia porcentual de área, la posición relativa de sus centros de gravedad o puntos medios, etc.).
  • Tiene número minimo-maximo de verices. (se genera si hay más de un objeto en la misma categoria)
    • Esta regla se genera si entre los diferentes objetos de la categoria la diferencia entre el minimo y el maximo es menor a la media.
  • Tiene N vectores como (se genera si hay más de un objeto de la misma categoria)
    • Regla que comprueba si en un determinado objeto se dan determinados vectores.
  • Tiene x lineas de longitud min - max. (se genera si hay más de un objeto de la misma categoría)
    • Regla que se crea si se detecta que en todos los objetos se tienen vectores con el mismo (o parecido) módulo.

A parte de estas en futuras versiones espero incluir la definición de contexto, es decir como se relacionan en el entorno los diferenetes elementos y si algún concepto es la unión de varios elementos aprendidos (por ejemplo cubiertos=tenedor+cuchillo+cuchara o texto=A+B+...+Z+a+...z+...) para lo que además habrá que generar más reglas.

Situación del proyecto

Disculpad que no haya actualizado el blog en más de una semana. Desde la última entrada que hice en el blog, el proyecto ha avanzado bastante. En primer lugar, he creado una rama en el repositorio del proyecto para la interfaz gráfica (GUI) de la aplicación local (concretamente en cusl5-yud/localApp/branches/v0.0.2). Con esto podré modificar la GUI de la aplicación con mayor libertad de la que tendría si estuviera modificando la rama principal de la aplicación.
Además, he añadido páginas de manual tanto en castellano como en inglés. Esto empieza a ser importante para documentar la aplicación, uno de los pasos en los que quiero avanzar ahora. Estas páginas de manual son accesibles dentro de la propia aplicación (descargando el proyecto del repositorio, y ejecutando el comando “nroff -man yud.1″ en la carpeta de documentación: $PROJECT_DIR/localApp/trunk/docs/man para visualizarla), o desde la página de la forja, en la que están subidas las páginas de manual en formato de texto. Estoy terminando también un manual para la creación de páginas de manual en entornos UNIX, así que en cuanto lo termine lo subiré tanto al blog como a la página del proyecto en la forja (en la sección de Documentos).
Por último, he trabajado en un script para descargar la lista de paquetes de software de todas las distribuciones de Ubuntu y parsearla, obteniendo el nombre de paquete, la descripción, la versión y el origen del paquete (universe, multiverse, …). Esta información se almacena después en una base de datos que maneja el módulo de python “db.py”.
Tenía intención de almacenar también las dependencias entre los paquetes de software en la base de datos, pero ésto no es importante más que a modo de información (puesto que al instalar un paquete instalará todas las dependencias con él), y dado que no hay forma en la página oficial de Ubuntu de obtener una lista de todas las dependencias, sino que debo ir paquete por paquete (y para cada distribución) parseando una página para sacar las dependencias, he dejado esto aparcado por el momento.
En la siguiente entrada comentaré los siguientes pasos que tengo intención de dar con el proyecto.

Distribuir contenido

Colabora