winston 发表于 2012-1-17 10:08:35

Lua学习笔记——Lua作为库嵌入到C

/*C++程序接收用户输入的字符串,把该字符串作为Lua的一个chunk送到stack中编译执行。*/
#include <stdio.h>
#include <string.h>
#include <lua.hpp>

int main(int argc, char* argv[]){
        char buff;
        int error = 0;
        lua_State* L=lua_open();
        if(0 == L){
                return -1;
        }
        luaL_openlibs(L);
       
        while (fgets(buff, sizeof(buff), stdin) != 0){
                error = luaL_loadbuffer(L, buff, strlen(buff), \
                        "line") || lua_pcall(L, 0, 0, 0);
                if(error){
                        fprintf(stderr, "%s", lua_tostring(L, -1));
                        lua_pop(L, 1);
                }
        }

        lua_close(L);
        return 0;
}/*
函数luaL_loadbuffer编译一段字符串为chunk, lua_pcall执行chunk.
lua_tostring(L, -1)拿到栈顶元素,并将其转换为字符串
*/
/*
@param errfunc if errfunc is 0, then error message returned on the stack is exactly the original error message. otherwise, errfunc is the stack index of an error handler function.In case of runtime errors, this function will be called with error message and its return valuewill be the message returned on the stack by lua_pcall.
@return zero in case of success or one of the following error codes(definded in lua.h)
LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc)

Loads a buffer as a Lua chunk.
@param name is the chunk name.
@return the same with lua_load function. 0 in case of success or LUA_ERRSYNTAX, LUA_ERRMEM.
int luaL_loadbuffer(lua_State* L, const char* buff, size_t sz, const char* name)

Changes in the API(Lua 5.1)
--The luaopen_* functions(to open libraries) cannot becalled directly, like a regular C function. They must be called through Lua, like a Lua function.
--Function lua_open was replaced by lua_newstate to allow the user to set a memory-allocation function. You can use luaL_newstate from the standard library to create a state with a standard allocation function (based on realloc)
--Functions luaL_getn and luaL_setn are deprecated. Use lua_objlen instead of luaL_getn and nothing instead of luaL_setn.
--Function luaL_checkudata now throws an error when the given value is not a userdata of expected type. (In Lua5.0 it returned NULL)
*/

/*
class Uncopyable{
public:
        virtual ~Uncopyable();
protected:
        Uncopyable();
private:
        Uncopyable(const Uncopyable& rhs);
        Uncopyable& operator=(const Uncopyable& rhs);
};

class Uninheritable{
public:
        Uninheritable* NewInstance();
        ~Uninheritable();
private:
        Uninheritable();
};
*/

/*
Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger the oldone, then the new elements are filled with nil. If index is 0, then all stack elements are removed.
void lua_settop (lua_State *L, int index);
--补充说明:设置index位置为栈顶。如果原先的栈顶大于index,则大于index的部分被清空,只保留小于等于index的部分。
*/

void Error(lua_State* L, const char* fmt, ...){
        va_list argp;
        va_start(argp, fmt);
        vfprintf(stderr, fmt, argp);
        va_end(argp);
        if(0 != L){
                lua_close(L);
                L = 0;
        }
        exit(EXIT_FAILURE);
}

bool Load(const char* filename, int* width, int*height){
        lua_State* L = luaL_newstate();
        if(0 == L){
                return false;
        }
        // luaL_openlibs(L);
        if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)){
                Error(L, "Cannot run configuration file: %s", \
                        lua_tostring(L, -1));
        }
        lua_getglobal(L, "width");
        lua_getglobal(L, "height");
        if(!lua_isnumber(L, -2)){
                Error(L, "'width' should be a number \n");
        }

        if(!lua_isnumber(L, -1)){
                Error(L, "'height' should be a number \n");
        }

        *width = (int)lua_tonumber(L, -2);
        *height = (int)lua_tonumber(L, -1);
        lua_close(L);
        return true;
}

/*example_2*/
int main(int argc, char* argv[]){
        if(2 > argc){
                return -1;
        }

        int width(0), height(0);
        if(Load(argv, &width, &height)){
                std::cout << "width = \t" << width << "\n";
                std::cout << "height = \t" << height << "\n";
        }
        return 0;
}
/*
--filename : configuration.lua
--configuration file for LuaTest appliation
horizontal = true
if horizontal then
        width = 1024
        height = 768
else
        width = 768
        height = 1024
end

命令行运行LuaTest控制台程序: LuaTest.exe configuration.lua
*/

/*
Push onto the stack the value of global name. It is defined as macro:
        #define lua_getglobal(L, s) lua_getfield(L, LUA_GLOBALSINDEX, s)
void lua_getglobal (lua_State *L, const char *name);

Pushes onto the stack the value t, where t is the value at given valid index.
void lua_getfield (lua_State *L, int index, const char *k);
*/

/*sample_3*/
#include <iostream>
#include <string.h>
#include <lua.hpp>

void Error(lua_State* L, const char* fmt, ...){
        va_list argp;
        va_start(argp, fmt);
        vfprintf(stderr, fmt, argp);
        va_end(argp);
        if(0 != L){
                lua_close(L);
                L = 0;
        }
        exit(EXIT_FAILURE);
}

const int MAX_COLOR = 255;
/*Assume that table is on the stack top*/
int GetField(lua_State* L, const char* key){
        int res;
        lua_pushstring(L, key);
        lua_gettable(L, -2); /*get background*/
        if(!lua_isnumber(L, -1)){
                Error(L, "invalid component in background color.");
        }

        res = (int)(lua_tonumber(L, -1) * MAX_COLOR);
        lua_pop(L, 1);       
        return res;
}

struct ColorRGB{
        unsigned char red, green, blue;
};

bool GetBackgroundColor(const char* filename, ColorRGB& rgb){       
        lua_State* L = luaL_newstate();
        if(0 == L){
                return false;
        }
        if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)){
                Error(L, "Cannot run configuration file : %s ", lua_tostring(L, -1));
        }

        /*push 全局变量background 到 stack.*/
        lua_getglobal(L, "background");
        if(!lua_istable(L, -1)){
                Error(L, "'background' is not a valid color table!");
        }

        rgb.red = GetField(L, "r");
        rgb.green = GetField(L, "g");
        rgb.blue = GetField(L, "b");

        lua_close(L);
        return true;
}

int main(int argc, char* argv[]){
        if(2 > argc){
                return -1;
        }

        ColorRGB backgroundColor= {0, 0, 0};
        if(GetBackgroundColor(argv, backgroundColor)){
                std::cout << "Red \t" << (int)backgroundColor.red << "\n";
                std::cout << "Green \t" << (int)backgroundColor.green << "\n";
                std::cout << "Blue \t" << (int)backgroundColor.blue << "\n";
        }
        return 0;
}

/*
Pushes onto the stack the value t, where t is the value at the given valid index and k is the value at the top of the stack.
把t入栈,t是栈中的一个table,由index来指定,k是栈顶的值。从命名可知t代表table,k代表key, t代表value.
This function pops the key from the stack (putting the resulting value in its place).
弹出将原先在栈顶的key,代之以value,即table

void lua_gettable (lua_State *L, int index);
*/

/*
Does the equivalent to t = v, where t is the value at the given valid index, v is the value at the top of the stack, and k is the value just below the top.
这条语句的作用相当于table = value, index 指定了table在栈中的位置。value是栈顶元素,key是栈顶元素的下一个元素。
This function pops both the key and the value from the stack.
赋值结束后,value和key将被弹出栈。
void lua_settable (lua_State *L, int index);
*/

/*
Pops n elements from the stack.
从栈中弹出n个元素
void lua_pop (lua_State *L, int n);
*/

/*
从stack中弹出一个值,并将这个值命名为 name。
Pops a value from the stack and sets it as the new value of global name.
void lua_setglobal (lua_State *L, const char *name);
*/

/*
Loads a Lua chunk (without running it). If there are no errors, lua_load pushes the compiled chunk as a Lua function on top of the stack. Otherwise, it push an error message.
The return values of lua_load are:
        LUA_OK: no error
        ...
int lua_load (lua_State *L,
            lua_Reader reader,
            void *data,
            const char *source,
            const char *mode);
*/


作者:Wu_Xiangwei 发表于2012-1-16 19:36:57 原文链接


页: [1]
查看完整版本: Lua学习笔记——Lua作为库嵌入到C