Kirjautuminen

Haku

Tehtävät

Koodit: C: Lua-skriptien käyttö

Kirjoittaja: vidar

Kirjoitettu: 11.06.2008 – 11.06.2008

Tagit: koodi näytille, vinkki

Joop. Nopealla selaamisella en löytänyt täältä Lua-vinkkiä, joten ajattelin sitten ajankuluksi lisätä semmoisen. Koodi koittaa olla C:tä.

Eli Lua on skriptikieli, joka on suunniteltu ympättäväksi mukaan suurempiin sovelluksiin. Tekoälyn tai käyttöliittymän tekoon Lua soveltuu hyvin, ja sitä käyttävätkin mm. SciTE, World of Warcraft, Crysis ja kasa muita kaupallisia softia.

Linkkejä:
http://www.lua.org/manual/5.1/ - Luan virallinen referenssimanuaali.
http://www.gamedev.net/reference/articles/article1932.asp - Gamedev.netin artikkeli aiheesta. Koodiesimerkit valitettavasti hiukan vanhentuneita.

Muita tutoja löytyy googlella, vaikka valitettavan harva on ajantasalla. .NETtiä varten on LuaInterface. Windows-binäärit voi ladata http://luabinaries.luaforge.net/download.html, Linuxille Luan luulisi löytyvän paketinhallinnasta.

Esimerkin pitäisi kääntyä näin:

cc lua_test.c -llua5.1 -o lua_test

lua_test.c

#include <stdio.h>

/* C++:aa käytettäessä joko extern "C" { ... }
 * includejen ympärille, tai suoraan #include "lua.hpp"
 */
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

/* Helpottaa. Tämmöisiä funkkareita voi passata Luaan. */
typedef int (*lua_func)(lua_State* lua);

/* Ajetaan filu. Mokoma osaa lukea tekstimuotoisia (.lua) tai
 * käännettyjä (.lub, kai :/) tavukoodifiluja. Kääntäminen onnistuu
 * luac -o <tulos.lub> <filu.lua> */
void do_file(lua_State* lua, char* filename) {
	if (luaL_dofile(lua, filename) != 0) {
		/* Otetaan luan pinon päältä virheilmoitus ja muutetaan se stringiksi. */
		fprintf(stderr, "%s\n", lua_tostring(lua, -1));
		/* Poistetaan virheilmoitus pinosta. */
		lua_pop(lua, 1);
	}
}

/* Sama pelkälle tekstille, ihan täydellisyyden vuoksi. */
void do_string(lua_State* lua, char* str) {
	if (luaL_dostring(lua, str) != 0) {
		fprintf(stderr, "%s\n", lua_tostring(lua, -1));
		lua_pop(lua, 1);
	}
}

/* Testifunktio, jota kutsutaan Lua-koodista. */
int summaa(lua_State* lua) {
	/* Luassa argumentteja voi passata niin paljon kuin lystää. */
	int argc = lua_gettop(lua);
	double sum = 0.0;
	int i = 0;

	printf("Saatiin %d argumenttia.\n", argc);

	for (i = 1; i != argc + 1; ++i) {
		/*
		 * Virheentarkistusta. i viittaa indeksiin pinossa:
		 * Lua kommunikoi C-softan kanssan pinon välityksellä. Ihan oikeaoppinen
		 * pino se ei ole, vaan siihen voi viitata indekseillä.
		 * Positiivinen luku on absoluuttinen indeksi pinoon, laskettu
		 * pinon alusta, negatiivinen taas lopusta. Paremman selityksen
		 * saa paremmista tutoriaaleista :/
		 */
		if (!lua_isnumber(lua, i)) {
			fprintf(stderr, "Argumentti %d ei ole numero.\n", i);
			continue;
		}

		/* Muutetaan argumentti numeroksi ja summataan. Luan numerot palautuvat
		 * C:hen doubleina. */
		sum += lua_tonumber(lua, i);
	}

	/* Lisätään palautusarvo pinoon. */
	lua_pushnumber(lua, sum);
	/* Palautetaan palautusarvojen määrä. */
	return 1;
}

int main(int argc, char** argv) {
	/* Lua-tila. Ajattele vaikka virtuaalikoneena. */
	lua_State* lua;

	/* lua_open() alustaa. */
	if ((lua = lua_open()) == 0) {
		fprintf(stderr, "Alustus kusee.");
		return 1;
	}

	/* Avataan kaikki peruskirjastot. */
	luaL_openlibs(lua);

	/* Avataan oma summaa-funktiomme käyttöön Lua-koodista. */
	lua_register(lua, "summaa", summaa);

	do_string(lua, "io.write(\"Toimii!\\n\");");

	do_file(lua, "testifilu.lua");

	/* Suljetaan Lua. */
	lua_close(lua);

	return 0;
}

testifilu.lua

io.write("Tämmönen versio käytössä: ", _VERSION, "\n\n");

-- Summaillaan ny si.
io.write("1000 + 500.5 - 40  + 0.75 = ", summaa(1000, 500.5, -40, 0.75), "\n");

Abaut tämmöstä pitäs tulostaa:

Toimii!
Tämmönen versio käytössä: Lua 5.1

Saatiin 4 argumenttia.
1000 + 500.5 - 40  + 0.75 = 1461.25

Kommentit

Metabolix [30.06.2008 00:16:21]

#

Hyvä vinkki! Riittävän yksinkertainen ja hyvin kommentoitu. Nyt ei tarvitse lähteä tätäkään etsimään englanniksi tuhannen rivin purkkakoodina.

Pekka Karjalainen [30.06.2008 08:46:09]

#

En tiennytkään, että Emacs käyttää Luaa. SciTE-editori kyllä käyttää skriptaukseen Lua-kieltä, mutta Emacs vaikuttaisi pitäytyneen ihan Elisp-linjalla.

Lisävinkki: Intelin prossuilla saa lisää nopeutta LuaJIT-kääntäjällä, jonka kanssa vastaavasti muistin kulutus on hieman isompi. Vielä tälle vuodelle on luvattu versio 2.0 ja osoite on: http://luajit.org

Yleensä tuon voi tiputtaa suoraan korvikkeeksi tavalliselle Lualle, ja kaikki toimii kuten ennen -- paitsi nopeammin.

vidar [02.07.2008 08:42:52]

#

Itse en Emacsia käytä, joten en sano varmaksi, mutta muistaisin lukeneeni jostain sen käyttävän Luaa. Tosin, en nyt näin jälkikäteen enää löydäkään viittausta asiaan, joten vaihdoin tekstin varmuudeksi viittamaan SciTEen.

Laitinen [02.07.2008 20:34:32]

#

Esim. Ion-ikkunointimanageri UNIX-systeemeihin (tai lähinnä linuxiin) käyttää myös luaa. Hieno koodivinkki myöskin :).

progo [03.07.2008 16:12:30]

#

Gentoossa kääntyy kunhan kirjasto on muodossa "lua", eli komentosikermä gcc luatesti.c -llua -o luatesti toimi. Asiavinkki totta tosiaan.

Createman [20.07.2008 09:01:05]

#

Hyvä vinkki.
Kiva kun tän saa nyt nopeesti täältä.

Itse tappelin vastaavat rivit kasaan (ja selvitin merkitykset), niin meni muutamia tunteja aivan hukkaan :P
Vanhaa syntaksia oli tarjolla useimmissa paikoissa :/

Laitinen [15.08.2008 18:43:11]

#

Tosiaan Emacsin kanssa mennyt varmaan Lisp ja Lua sekaisin.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta