lua的C接口

来源:互联网 发布:iphone8值得买吗 知乎 编辑:程序博客网 时间:2024/05/16 07:18
用lua快一年了,因为引擎部分比较少改动,所以一直没用过它的C接口,都是在写脚本。年前看书时写了一个小的demo做学习用,好像当时遇到些困难,但是没有记录下来,几乎都忘了。这里贴点源码出来做备忘吧:)lua的语法还是比较简单,其官网(www.lua.org)上有电子文档(www.lua.org/pil/),看一看就会了。不过学会一门语言的语法跟用好一门语言还是两回事,好在它的源码也不多,多看看源码理解就深了。
首先说我比较讨厌lua的几个地方:
1、把数组和table混在一起,数组可以很方便取得size,而table就只能自己遍历去数。
2、没有continue,经常出现循环里面嵌套N层if。
3、最最无聊的就是变量默认是global的,要显示声明local才是本地变量。
大概就这几个公认的问题了,下面贴代码:)

 

程序实现了一个lua解释器,其实就是读入lua语句然后解释执行,用了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();//创建一个lua运行环境,可以传入一个内存管理参数
        luaL_openlibs(L);//打开常用lib
        
if ( ! init_script() )//load脚本
                
return -1
        register_api(L);//注册api
        create_table(L);//创建一个table
        
char* input = NULL;
        
while(1)
        
{   
                input 
= readline(">>");//提示输入
                
if (input)
                
{   
                        
if ( *input )
                        
{   
                                
if( exelua(input) )//执行输入的语句
                                        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, 000);//load并执行 
        
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, 01, 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)//创建一个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下编译通过。

原创粉丝点击