C/C++与Lua交互(C实现的Lua编译器的例子)

#include <stdio.h>
#include <string.h>

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#pragma comment(lib,"C:\\Program Files\\Lua\\5.1\\lib\\lua51.lib")

int main (void)
{
    char buff[256];
    int error;
    lua_State *L = lua_open();
    //luaL_openlibs(L);
    luaopen_base(L);
    luaopen_table(L);
    luaopen_io(L);
    luaopen_string(L);
    luaopen_math(L);
    while (fgets(buff, sizeof(buff), stdin) != NULL) {
        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;
}
该版本是Lua 5.0的例子,若用于Lua 5.1做解释器,运行到红色处会出现
PANIC: unprotected error in call to Lua API (no calling environment)
修改后的版本为:
#include <stdio.h>
#include <string.h>

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#pragma comment(lib,"C:\\Program Files\\Lua\\5.1\\lib\\lua51.lib")

int main (void)
{
    char buff[256];
    int error;
    lua_State *L = lua_open();
    luaL_openlibs(L);
    //luaopen_base(L);
    //luaopen_table(L);
    //luaopen_io(L);
    //luaopen_string(L);
    //luaopen_math(L);
    //printf("xxxx\n");
    while (fgets(buff, sizeof(buff), stdin) != NULL) {
        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;
}

头文件lua.h定义了Lua提供的基础函数。其中包括创建一个新的Lua环境的函数(如lua_open),调用Lua函数(如lua_pcall)的函数,读取/写入Lua环境的全局变量的函数,注册可以被Lua代码调用的新函数的函数,等等。所有在lua.h中被定义的都有一个lua_前缀。

头文件lauxlib.h定义了辅助库(auxlib)提供的函数。同样,所有在其中定义的函数等都以luaL_打头(例如,luaL_loadbuffer)。辅助库利用lua.h中提供的基础函数提供了更高层次上的抽象;所有Lua标准库都使用了auxlib。基础API致力于economy and orthogonality,相反auxlib致力于实现一般任务的实用性。当然,基于你的程序的需要而创建其它的抽象也是非常容易的。需要铭记在心的是,auxlib没有存取Lua内部的权限。它完成它所有的工作都是通过正式的基本API。

Lua库没有定义任何全局变量。它所有的状态保存在动态结构lua_State中,而且指向这个结构的指针作为所有Lua函数的一个参数。这样的实现方式使得Lua能够重入(reentrant)且为在多线程中的使用作好准备。

创建一个state并将标准库载入之后,就可以着手解释用户的输入了。对于用户输入的每一行(while (fgets(buff, sizeof(buff), stdin) ),C程序首先调用luaL_loadbuffer编译这些Lua代码。如果没有错误,这个调用返回零并把编译之后的chunk压入栈。(记住,我们将在下一节中讨论魔法般的栈)之后,C程序调用lua_pcall,它将会把chunk从栈中弹出并在保护模式下运行它。和luaL_laodbuffer一样,lua_pcall在没有错误的情况下返回零。在有错误的情况下,这两个函数都将一条错误消息压入栈;我们可以用lua_tostring来得到这条信息、输出它,用lua_pop将它从栈中删除。

相关推荐