在lua中使用C语言编写的库

来源:互联网 发布:肯德基 麦当劳 知乎 编辑:程序博客网 时间:2024/05/19 09:42

因为lua比较小巧所以他本身并没有包含强大的库,但我们可以为lua扩展库,今天主要说明以下怎么在lua中使用C语言编写的库(windows下生成dll,linux下生成so),在库函数中必须包含一个luaopen_yourlibname的函数,库名可以自己定,该函数也是lua_CFunction的类型,主要作用是将你所编写的库中的函数使用lua_register函数将其注册供lua中使用。通过下面的代码可以看到lua的扩展性非常强大。在lua中只需要require "yourlibname"即可或者用loadlib函数.  下面这个例子是为lua提供一个遍历目录的库,

C库代码如下:

[cpp] view plaincopy
  1. #include <sys/types.h>  
  2. #include <dirent.h>  
  3. #include <sys/stat.h>  
  4. #include <string.h>  
  5. #include <malloc.h>  
  6.   
  7. #include <lua/lua.h>  
  8. #include <lua/lauxlib.h>  
  9. #include <lua/lualib.h>  
  10.   
  11. #ifndef MAX_PATH  
  12. #define MAX_PATH        260  
  13. #endif  
  14.   
  15. enum   
  16. {  
  17.     PQFT_UNKNOWN = 0,  
  18.     PQFT_FILE = 1,  
  19.     PQFT_DIR = 2  
  20. };  
  21.   
  22.   
  23. typedef struct   
  24. {  
  25.     DIR *   dir;  
  26.     char    curr_path[MAX_PATH];  
  27. }PQDIR;  
  28.   
  29.   
  30. static int search_dir_first(lua_State *L)  
  31. {  
  32.     PQDIR * pd = NULL;  
  33.     const char *dir_path = luaL_checkstring(L, 1);  
  34.   
  35.     if ( dir_path ) {  
  36.         pd = (PQDIR *)malloc(sizeof(PQDIR));  
  37.         if ( pd ) {   
  38.             pd->dir = opendir(dir_path);  
  39.             if ( pd->dir ) {  
  40.                 memset(pd->curr_path, 0, MAX_PATH);                
  41.                 memcpy(pd->curr_path, dir_path, strlen(dir_path));  
  42.                 lua_pushboolean(L, 1);  
  43.                 lua_pushlightuserdata(L, pd);  
  44.                 return 2;  
  45.             }         
  46.         }     
  47.     }  
  48.       
  49.     lua_pushboolean(L, 0);  
  50.     lua_pushnil(L);  
  51.     return 2;  
  52. }  
  53.   
  54. static int search_dir_next(lua_State *L)  
  55. {  
  56.     char filepath[MAX_PATH];  
  57.     struct dirent *ent = NULL;  
  58.     struct stat file_stat;  
  59.     PQDIR *pd = (PQDIR *)lua_touserdata(L, 1);  
  60.       
  61.     if ( pd ) {  
  62.         if ( (ent = readdir(pd->dir)) ) {  
  63.             lua_pushboolean(L, 1);  
  64.             lua_pushstring(L, ent->d_name);  
  65.             sprintf(filepath, "%s/%s", pd->curr_path, ent->d_name);  
  66.             lstat(filepath, &file_stat);  
  67.             if ( S_ISDIR(file_stat.st_mode) && !S_ISLNK(file_stat.st_mode) ) {  
  68.                 lua_pushnumber(L, PQFT_DIR);  
  69.             } else if ( S_ISREG(file_stat.st_mode) && !S_ISLNK(file_stat.st_mode) ) {  
  70.                 lua_pushnumber(L, PQFT_FILE);  
  71.             } else {  
  72.                 lua_pushnumber(L, PQFT_UNKNOWN);  
  73.             }  
  74.             return 3;  
  75.         }     
  76.     }  
  77.   
  78.     lua_pushboolean(L, 0);  
  79.     lua_pushnil(L);  
  80.     lua_pushnil(L);   
  81.     return 3;  
  82. }  
  83.   
  84. static int search_dir_finish(lua_State *L)  
  85. {  
  86.     PQDIR *pd = (PQDIR *)lua_touserdata(L, 1);  
  87.     if ( pd ) {  
  88.         closedir(pd->dir);  
  89.         free(pd);  
  90.         pd = NULL;  
  91.     }  
  92.     return 0;  
  93. }  
  94.   
  95. int luaopen_pqdir(lua_State *L)  
  96. {  
  97.     lua_pushnumber(L, PQFT_UNKNOWN);  
  98.     lua_setglobal(L, "PQFT_UNKNOWN");  
  99.     lua_pushnumber(L, PQFT_FILE);  
  100.     lua_setglobal(L, "PQFT_FILE");  
  101.     lua_pushnumber(L, PQFT_DIR);  
  102.     lua_setglobal(L, "PQFT_DIR");     
  103.   
  104.     lua_register(L, "search_dir_first", search_dir_first);  
  105.     lua_register(L, "search_dir_next", search_dir_next);  
  106.     lua_register(L, "search_dir_finish", search_dir_finish);  
  107.   
  108.     return 0;  
  109. }  
使用gcc -shared pqdir.c -o pqdir.so -llua -ldl -lm命令将其生存so文件


lua代码如下:

[cpp] view plaincopy
  1. require "pqdir"  
  2.   
  3. function traverse_dir(dirpath)  
  4.     print("search: " .. dirpath)  
  5.     local bok, dir = search_dir_first(dirpath)  
  6.     if bok then  
  7.         while true do  
  8.             local b, filename, filetype = search_dir_next(dir)  
  9.             if b then  
  10.                 local fullpath = dirpath .. "/" .. filename  
  11.                 if filetype == PQFT_DIR then  
  12.                     if filename == "." then  
  13.                     elseif filename == ".." then  
  14.                     else traverse_dir(fullpath)  
  15.                     end  
  16.                 else  
  17.                     print(fullpath)  
  18.                 end   
  19.             else  
  20.                 break         
  21.             end  
  22.         end  
  23.         search_dir_finish(dir)  
  24.     end  
  25. end  
  26.   
  27. traverse_dir("/usr")  

0 0
原创粉丝点击