因为lua比较小巧所以他本身并没有包含强大的库,但我们可以为lua扩展库,今天主要说明以下怎么在lua中使用C语言编写的库(windows下生成dll,linux下生成so),在库函数中必须包含一个luaopen_yourlibname的函数,库名可以自己定,该函数也是lua_CFunction的类型,主要作用是将你所编写的库中的函数使用lua_register函数将其注册供lua中使用。通过下面的代码可以看到lua的扩展性非常强大。在lua中只需要require "yourlibname"即可或者用loadlib函数. 下面这个例子是为lua提供一个遍历目录的库,
C库代码如下:
- #include <sys/types.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <malloc.h>
- #include <lua/lua.h>
- #include <lua/lauxlib.h>
- #include <lua/lualib.h>
- #ifndef MAX_PATH
- #define MAX_PATH 260
- #endif
- enum
- {
- PQFT_UNKNOWN = 0,
- PQFT_FILE = 1,
- PQFT_DIR = 2
- };
- typedef struct
- {
- DIR * dir;
- char curr_path[MAX_PATH];
- }PQDIR;
- static int search_dir_first(lua_State *L)
- {
- PQDIR * pd = NULL;
- const char *dir_path = luaL_checkstring(L, 1);
- if ( dir_path ) {
- pd = (PQDIR *)malloc(sizeof(PQDIR));
- if ( pd ) {
- pd->dir = opendir(dir_path);
- if ( pd->dir ) {
- memset(pd->curr_path, 0, MAX_PATH);
- memcpy(pd->curr_path, dir_path, strlen(dir_path));
- lua_pushboolean(L, 1);
- lua_pushlightuserdata(L, pd);
- return 2;
- }
- }
- }
- lua_pushboolean(L, 0);
- lua_pushnil(L);
- return 2;
- }
- static int search_dir_next(lua_State *L)
- {
- char filepath[MAX_PATH];
- struct dirent *ent = NULL;
- struct stat file_stat;
- PQDIR *pd = (PQDIR *)lua_touserdata(L, 1);
- if ( pd ) {
- if ( (ent = readdir(pd->dir)) ) {
- lua_pushboolean(L, 1);
- lua_pushstring(L, ent->d_name);
- sprintf(filepath, "%s/%s", pd->curr_path, ent->d_name);
- lstat(filepath, &file_stat);
- if ( S_ISDIR(file_stat.st_mode) && !S_ISLNK(file_stat.st_mode) ) {
- lua_pushnumber(L, PQFT_DIR);
- } else if ( S_ISREG(file_stat.st_mode) && !S_ISLNK(file_stat.st_mode) ) {
- lua_pushnumber(L, PQFT_FILE);
- } else {
- lua_pushnumber(L, PQFT_UNKNOWN);
- }
- return 3;
- }
- }
- lua_pushboolean(L, 0);
- lua_pushnil(L);
- lua_pushnil(L);
- return 3;
- }
- static int search_dir_finish(lua_State *L)
- {
- PQDIR *pd = (PQDIR *)lua_touserdata(L, 1);
- if ( pd ) {
- closedir(pd->dir);
- free(pd);
- pd = NULL;
- }
- return 0;
- }
- int luaopen_pqdir(lua_State *L)
- {
- lua_pushnumber(L, PQFT_UNKNOWN);
- lua_setglobal(L, "PQFT_UNKNOWN");
- lua_pushnumber(L, PQFT_FILE);
- lua_setglobal(L, "PQFT_FILE");
- lua_pushnumber(L, PQFT_DIR);
- lua_setglobal(L, "PQFT_DIR");
- lua_register(L, "search_dir_first", search_dir_first);
- lua_register(L, "search_dir_next", search_dir_next);
- lua_register(L, "search_dir_finish", search_dir_finish);
- return 0;
- }
lua代码如下:
- require "pqdir"
- function traverse_dir(dirpath)
- print("search: " .. dirpath)
- local bok, dir = search_dir_first(dirpath)
- if bok then
- while true do
- local b, filename, filetype = search_dir_next(dir)
- if b then
- local fullpath = dirpath .. "/" .. filename
- if filetype == PQFT_DIR then
- if filename == "." then
- elseif filename == ".." then
- else traverse_dir(fullpath)
- end
- else
- print(fullpath)
- end
- else
- break
- end
- end
- search_dir_finish(dir)
- end
- end
- traverse_dir("/usr")