在lua中使用C語言編寫的庫

因爲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;
}

使用gcc -shared pqdir.c -o pqdir.so -llua -ldl -lm命令將其生存so文件


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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章