C/C++与lua的交互

C/C++与lua之间能过实现交互,它的原理是:
1.lua里面的API都是用C写的。
2.lua跟C/C++的交互是通过一个虚拟stack来进行数据的沟通的。在VS工程中,我们需要加入C API的头文件lua.h, luaconfig.h , lualib.h, luaxlib.h 。这几个头文件都是lua源代码,可以直接下载使用。lua.h提供原子级别的API,对栈的基本操作都在里面实现,里面的API都是lua_开头。luaxlib.h 定义了辅助库提供的函数,它的所有定义都以luaL_开头,辅助库是一个使用lua.h中的API编写出的一个较高的抽象层。下面看下完整源代码:

#include "stdafx.h"  
#include "stdio.h"  
extern "C"  
{  
    #include "lua.h"   //提供原子级别的API
    #include "lualib.h"  
    #include "lauxlib.h"  //定义了辅助哭提供的函数
};  //lua头文件中的API都是用C写的  

#pragma comment(lib,"lua5.1.lib")       //让程序知道调用的lua里面的API可以直接在这个库里面找  

//这个函数,我们实现将压进stack里面的所有数据,从base到top,根据不同类型打印出来  
void stackDump(lua_State *L)  
{  
    int i;  
    int top = lua_gettop(L);  //获取stack大小  
    for ( i = 1;i <= top;i++ )  
    {  
        int type = lua_type(L, i);  
        switch(type)  
        {  
        case LUA_TSTRING:  
            {  
                printf("%s",lua_tostring(L, i));  //lua库中的函数,添加了头文件,可以直接使用
                break;  
            }  

        case LUA_TBOOLEAN:  
            {  
                printf(lua_toboolean(L, i)?"true":"false");  
                break;  
            }  
        case LUA_TNUMBER:  
            {  
                printf("%g",lua_tonumber(L, i));  
                break;  
            }  
        default:  
            {  
                printf("%s",lua_typename(L ,i));  
                break;  
            }  
        }  
        printf(" ");  
    }  
    printf("\n");  
}  


int _tmain(int argc, _TCHAR* argv[])  
{  
    lua_State *L;    //创建一个lua_State实例
    L = luaL_newstate();    //必须要创建lua_State环境,stack存在于这个环境中  
    luaL_openlibs(L);   //加载lua静态链接库lua5.1.lib  
    lua_pushboolean(L,true);  
    lua_pushinteger(L,2);  
    lua_pushnumber(L,2.333);  
    lua_pushstring(L,"then");   //分别压入了四个不同类型的元素,现在stack里面,从base到top依次为 true , 2 , 2.333 ,then  
    stackDump(L);           //打印结果 从base到top为 true , 2 , 2.333 ,then  
    printf("stay here");  
    return 0;  
}  

C API. Lua既是一种扩展语言,也是一种可扩展语言;说它是扩展语言,意思是C/C++可以用lua进行扩展,这时C/C++拥有控制权,lua是一个库,这种形式的C/C++代码称为“应用程序代码”;说它是可扩展语言,意思是lua自身也可以通过在lua环境中注册用C语言(或其他语言)实现的函数,然后lua可以直接调用这些函数,这时lua拥有控制权,C是一个库,这种形式的C代码称为“库代码”。这就是C跟lua交互的两种形式。应用程序代码与库代码都使用相同的API来与lua通信,这些API就是C API

C API

Lua脚本实现交互提供了一系列的C API,常用API有:

luaL_newstate函数用于初始化一个lua_State实例
luaL_openlibs函数用于打开Lua中的所有标准库,如io库、string库等。
luaL_loadbuffer编译了buff中的Lua代码,如果没有错误,则返回0,同时将编译后的程序块压入虚拟栈中。
lua_pcall函数会将程序块从栈中弹出,并在保护模式下运行该程序块。执行成功返回0,否则将错误信息压入栈中。
lua_tostring函数中的-1,表示栈顶的索引值,栈底的索引值为1,以此类推。该函数将返回栈顶的错误信息,但是不会将其从栈中弹出。
lua_pop是一个宏,用于从虚拟栈中弹出指定数量的元素,这里的1表示仅弹出栈顶的元素。
lua_close用于释放状态指针所引用的资源
Lua针对每种C类型,都有一个C API函数与之对应,如:
void lua_pushnil(lua_State* L);  --nil值
void lua_pushboolean(lua_State* L, int b); --布尔值
void lua_pushnumber(lua_State* L, lua_Number n); --浮点数
void lua_pushinteger(lua_State* L, lua_Integer n);  --整型
void lua_pushlstring(lua_State* L, const char* s, size_t len); --指定长度的内存数据
void lua_pushstring(lua_State* L, const char* s);  --以零结尾的字符串,其长度可由strlen得出
Lua提供了一组特定的函数用于检查返回元素的类型,如:
int lua_isboolean (lua_State *L, int index);
int lua_iscfunction (lua_State *L, int index);
int lua_isfunction (lua_State *L, int index);
int lua_isnil (lua_State *L, int index);
int lua_islightuserdata (lua_State *L, int index);
int lua_isnumber (lua_State *L, int index);
int lua_isstring (lua_State *L, int index);
int lua_istable (lua_State *L, int index);
int lua_isuserdata (lua_State *L, int index);
 以上函数,成功返回1,否则返回0。需要特别指出的是,对于lua_isnumber而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型

C/C++与lua交互的总结:
1.引入lua的库函数

extern "C"  
{  
    #include "lua.h"   //提供原子级别的API
    #include "lualib.h"  
    #include "lauxlib.h"  //定义了辅助哭提供的函数
};//C++代码中,用extern "C" 区别c代码,因为lua头文件中的API都是用C写的

2.创建一个lua_State对象

lua_State *L;    //创建一个lua_State实例,lua_State主要是管理一个lua虚拟机的执行环境, 一个lua虚拟机可以有多个执行环境。Lua虚拟机通过维护这样一个虚拟栈来实现两种之间的通信

//C/C++与lua的数据通信
//Lua虚拟机提供Lua_State这样一种数据结构。任何一种数据从C\C++传入Lua虚拟机中,Lua都会将这类数据转换为一种通用的结构lua_TValue,并且将数据复制一份,将其压入虚拟栈中

3.初始化实例

L = luaL_newstate();    //必须要创建lua_State环境,stack存在于这个环境中

4.打开Lua中的所有标准库

  luaL_openlibs(L);   //加载lua静态链接库lua5.1.lib 

5.向stack中添加数据

    lua_pushboolean(L,true);  
    lua_pushinteger(L,2);  
    lua_pushnumber(L,2.333);  
    lua_pushstring(L,"then"); //类似于栈,第一个数据放在栈底,API使用“索引”来引用栈中的元素,第一个压入栈的为1,第二个为2,依此类推。我们也可以使用负数作为索引值,其中-1表示为栈顶元素,-2为栈顶下面的元素,同样依此类推

6.将stack中的数据读出来

 stackDump(L)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值