LUA > C függvény elérése > Könyvtárlistázás

Cél: Könyvár tartalmának listázása LUA-ban

Működés:

Nézzük a LUA értelmező szemszögéből. A require függvény megpróbálja behúzni a modult: a megadott paramétert , .dll vagy .lua kiterjesztéssel a LUA_PATH vagy LUA_CPATH környezeti változók elérési útjaiban. Ha talált egy dll-t, meghívja a luaopen_dir függvényt, ami a Lua állapotváltozót adja át, egy lua_State típusra mutató pointert L. Az L-be ezután regisztrálni kell a modul nevét. A luaL_register harmadik paraméterként olyan lual_Reg rekordokat tartalmazó tömböt vár, aminek utolsó eleme a {NULL,NULL} rekord. A luaL_reg rekord a függvény nevéből LUA-ban és a hivatkozott függvény C nevét tartalmazza. Végre elérkezünk az l_dir függvényhez, ami valóban csinál valamit.

(1) Megnyitjuk a megadott path-ot
(1.a) ha nincs ilyen könyvtár egy nil-t és egy hibaüzenetet dobunk vissza
(1.b) ha a könyvtár létezik készítünk egy táblát és feltöltjük a könyvtárban található elemekkel.

(1.a)-nál a luaverembe pakoljuk a nil-t majd a hibaüzenetet
(1.b)-nél létrehozzuk a táblát, majd ciklusban verembe helyezzük a sorszámot, majd a könyvtárbejegyzés nevét.

Még mindig a ciklusban maradva az igazán izgalmas rész ez: lua_settable(L, -3);

Ez végzi a táblafeltöltést kulccsal és értékkel: az index-szel határozzuk meg a tábla helyét a veremben. A verem tetejét a "-1" index jelöli! Mivel két elemet bedobtunk a verembe, így a tábla hátrébb szorult, jelenlegi verempozíciója 3-mal visszább van.

Használat:


require "dir"
for k,v in pairs(dir.dir(".")) do
   print(k,v)
end

Fordítás


$ cc -o dir.so -shared -Wall dir.c

Kód:


#include <dirent.h>
#include <errno.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static int l_dir (lua_State *L) {
      DIR *dir;
      struct dirent *entry;
      int i;
      const char *path = luaL_checkstring(L, 1);
    
      /* open directory */
      dir = opendir(path);
      if (dir == NULL) {  /* error opening the directory? */
        lua_pushnil(L);  /* return nil and ... */
        lua_pushstring(L, strerror(errno));  /* error message */
        return 2;  /* number of results */
      }
    
      /* create result table */
      lua_newtable(L);
      i = 1;
      while ((entry = readdir(dir)) != NULL) {
        lua_pushnumber(L, i++);  /* push key */
        lua_pushstring(L, entry->d_name);  /* push value */
        lua_settable(L, -3);
      }
    
      closedir(dir);
      return 1;  /* table is already on top */
    }

static const struct luaL_Reg dir_funcs[] = {
  { "dir",	l_dir },
  { NULL, NULL }
};

int luaopen_dir(lua_State *L){
	
	luaL_register(L, "dir", dir_funcs);
	return 1;
}

Fordítás WIN alatt.

A dirent.h tipikusan POSIX rendszeren érhető el, az MSVC fordító ilyet nem talál. Ezért használunk egy nem hivatalos dirent.h-t winre:

http://www.softagalleria.net/dirent.php

A header és lib fájlok a c:\Program Files\lua\5.1\src mappában találhatóak, amit a compiler /I kapcsolójával állíthatunk be.
Linkelésnél arra kell figyelnünk, hogy a kimenet DLL legyen, a lua LIB-je elérhető legyen és a DLL exportálja a luaopen_dir függvényt hiszen a lua értelmező ezt fogja keresni a dll neve alapján(luaopen_ + < dll neve >)


D:\Projektek\LuaC >cl /I"c:\Program Files\lua\5.1\src" /c dir.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

dir.c
dir.c(17) : warning C4996: 'strerror' was declared deprecated
        C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE\string.h(125) : se
e declaration of 'strerror'
        Message: 'This function or variable may be unsafe. Consider using strerr
or_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online h
elp for details.'

D:\Projektek\LuaC > link /export:luaopen_dir /dll dir.obj
 "c:\Program Files\lua\5.1\src\lua5.1.lib"

Teszt:


> lua test_dir.lua
D:\Projektek\LuaC>lua test_dir.lua
1       .
2       ..
3       dir.c
4       dir.dll
5       dir.exp
6       dir.lib
7       dir.obj
8       dirent-1.10.zip
9       dirent.h
10      test_dir.lua

Irodalom

[1] lua_settable rövid leírás, http://pgl.yoyo.org/luai/i/lua_settable
[2] lua_settable részletesebben, http://www.lua.org/pil/25.1.html