Lua游戲開發(fā)中關于C接口學習教程
Lua游戲開發(fā)中關于C接口是本文要介紹的內容,主要是來學習LUA中關于C接口的使用方法,具體內容的實現來看本文詳解。
用lua快一年了,因為引擎部分比較少改動,所以一直沒用過它的C接口,都是在寫腳本。年前看書時寫了一個小的demo做學習用,好像當時遇到些困難,但是沒有記錄下來,幾乎都忘了。這里貼點源碼出來做備忘吧:)lua的語法還是比較簡單,其官網(www.lua.org)上有電子文檔(www.lua.org/pil/),看一看就會了。不過學會一門語言的語法跟用好一門語言還是兩回事,好在它的源碼也不多,多看看源碼理解就深了。
首先說我比較討厭lua的幾個地方:
1、把數組和table混在一起,數組可以很方便取得size,而table就只能自己遍歷去數。
2、沒有continue,經常出現循環(huán)里面嵌套N層if。
3、最最無聊的就是變量默認是global的,要顯示聲明local才是本地變量。
大概就這幾個公認的問題了,下面貼代碼:)
程序實現了一個lua解釋器,其實就是讀入lua語句然后解釋執(zhí)行,用了readline是為了輸入方便。另外啟動的時候load了一個叫init.lua的腳本文件,提供了幾個api供腳本使用,全部代碼如下:(csdn怎么不提供附件功能呢)
- main.hpp
- #include <unistd.h>
- #include <sys/param.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <iostream>
- #include <readline/readline.h>
- #include <readline/history.h>
- #include <lua.hpp>
- extern lua_State *L;
- bool exelua(const char*);
- bool init_script();
- int lua_getcwd(lua_State*);
- int lua_dir(lua_State*);
- void register_api(lua_State*);
- void create_table(lua_State*);
- main.cpp
- #include "main.hpp"
- lua_State *L;
- int main(int argc, char** argv)
- ...{
- L = luaL_newstate();//創(chuàng)建一個lua運行環(huán)境,可以傳入一個內存管理參數
- luaL_openlibs(L);//打開常用lib
- if ( ! init_script() )//load腳本
- return -1;
- register_api(L);//注冊api
- create_table(L);//創(chuàng)建一個table
- char* input = NULL;
- while(1)
- ...{
- input = readline(">>");//提示輸入
- if (input)
- ...{
- if ( *input )
- ...{
- if( exelua(input) )//執(zhí)行輸入的語句
- add_history(input);//增加到歷史命令
- }
- free(input);
- input = NULL;
- }
- else
- ...{
- break;
- }
- }
- lua_close(L);
- return 0;
- }
- bool exelua(const char* line)
- ...{
- int error = luaL_loadbuffer(L, line, strlen(line), "line") || lua_pcall(L, 0, 0, 0);//load并執(zhí)行
- if ( error )
- ...{
- std::cerr << lua_tostring(L, -1) << std::endl;
- lua_pop(L, 1);
- return false;
- }
- return true;
- }
- bool init_script()
- ...{
- if ( luaL_dofile(L, "init.lua") != 0 )
- ...{
- std::cerr << "load init.lua failed ";
- return false;
- }
- lua_pushnumber(L, 1);//傳入參數
- lua_getglobal(L, "__init__");//獲取腳本中__init__變量
- if ( lua_isfunction(L, -1) )//判斷__init__是否一個函數
- ...{
- if ( lua_pcall(L, 0, 1, NULL) != 0 )//調用__init__
- ...{
- std::cerr << "call __init__ error ";
- return false;
- }
- int ret = lua_tonumber(L, -1) || lua_toboolean(L, -1);//取得__init__的返回值
- lua_pop(L, 1);
- if ( !ret )
- ...{
- std::cerr << "__init__ failed ";
- return false;
- }
- }
- return true;
- }
- api.cpp
- #include <dirent.h>
- #include "main.hpp"
- int lua_getcwd(lua_State* L)//獲取當前工作目錄
- ...{
- char path[MAXPATHLEN];
- bzero(path, MAXPATHLEN);
- if (lua_gettop(L) != 0 ) //不需要參數
- ...{
- luaL_argerror(L, 0, "no arg expected");
- return 0;
- }
- if ( !getcwd(path, MAXPATHLEN) )
- ...{
- luaL_error(L, "getcwd error %d, %s", errno, strerror(errno));
- return 0;
- }
- lua_pushlstring(L, path, strlen(path));//將返回值壓棧
- return 1;//返回返回值個數
- }
- int lua_dir(lua_State* L)//取得目錄下元素
- ...{
- const char* path = luaL_checkstring(L, 1);
- DIR* dir = opendir(path);
- if ( !dir )
- ...{
- lua_pushnil(L);
- lua_pushstring(L, strerror(errno));
- return 2;
- }
- int i = 1;
- struct dirent *ent;
- lua_newtable(L);//把所有元素放到一個table中,以數組返回
- while( ent = readdir(dir) )
- ...{
- lua_pushnumber(L, i++);
- lua_pushstring(L, ent->d_name);
- lua_settable(L, -3);
- }
- closedir(dir);
- return 1;
- }
- void register_api(lua_State* L)//注冊api
- ...{
- lua_register(L, "getcwd", lua_getcwd);//腳本中可以使用getcwd調用lua_getcwd
- lua_register(L, "dir", lua_dir);
- const luaL_Reg mylib[] =
- ...{
- ...{"getcwd", lua_getcwd},
- ...{"dir", lua_dir},
- ...{NULL, NULL},
- };
- luaL_register(L, "tlib", mylib);//注冊一個名為tlib的模塊,tlib.getcwd()
- }
- void create_table(lua_State* L)//創(chuàng)建一個table
- ...{
- lua_newtable(L);
- lua_pushnumber(L, 123);
- lua_setfield(L, -2, "id");
- lua_pushcfunction(L, lua_getcwd);
- lua_setfield(L, -2, "fun");
- lua_setglobal(L, "tb");
- }
- init.lua
- function __init__()
- print("__init__ ok")
- return 1;
- end
- Makefile CPPFLAGS=-Wall -g -O0 -I /usr/local/include/lua51/
- LIB=-L/usr/local/lib/lua51/ -llua -lreadline
- CC=g++
- SRC=main.cpp api.cpp
- OBJ=${SRC:%.cpp=%.o}
- all: depend main
- depend:
- @$(CC) -MM $(SRC) > .depend
- -include .depend
- main: $(OBJ)
- $(CC) $(OBJ) $(CPPFLAGS) $(LIB) -o $@
- clean:
- -rm -rf *.o main .depend
以上代碼在freebsd 6.2 gcc 3.4.6 lua 5.1.2下編譯通過。
小結:Lua游戲開發(fā)中關于C接口學習教程的內容介紹完了,希望通過本文的學習能對你有所幫助!