C\C++和Lua是如何进行通信的?

开发 后端 前端
lua本身就是用标准C编写的,它的优点是小巧和灵活,而且又是动态语言,是解释执行的,所以适合用在游戏和一些嵌入式环境里。下面将实现Lua和其他语言之间的通信……

为了实现Lua和其他语言之间的通信,Lua虚拟机为C\C++提供了两个特性:

一,Lua_State状态机

lua_State主要是管理一个lua虚拟机的执行环境, 一个lua虚拟机可以有多个执行环境。Lua虚拟机通过维护这样一个虚拟栈来实现两种之间的通信,lua_State定义如下:

  1. struct lua_State {  
  2.   CommonHeader;  
  3.   lu_byte status;  
  4.   StkId top;  /* first free slot in the stack */ 
  5.   global_State *l_G;  
  6.   CallInfo *ci;  /* call info for current function */ 
  7.   const Instruction *oldpc;  /* last pc traced */ 
  8.   StkId stack_last;  /* last free slot in the stack */ 
  9.   StkId stack;  /* stack base */ 
  10.   int stacksize;  
  11.   unsigned short nny;  /* number of non-yieldable calls in stack */ 
  12.   unsigned short nCcalls;  /* number of nested C calls */ 
  13.   lu_byte hookmask;  
  14.   lu_byte allowhook;  
  15.   int basehookcount;  
  16.   int hookcount;  
  17.   lua_Hook hook;  
  18.   GCObject *openupval;  /* list of open upvalues in this stack */ 
  19.   GCObject *gclist;  
  20.   struct lua_longjmp *errorJmp;  /* current error recover point */ 
  21.   ptrdiff_t errfunc;  /* current error handling function (stack index) */ 
  22.   CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */ 
  23. }; 

1,虚拟栈的管理, 包括管理整个栈和当前函数使用的栈的情况

2,CallInfo的管理, 包括管理整个CallInfo数组和当前函数的CallInfo

3,hook相关的, 包括hookmask, hookcount, hook函数等

4,global_State是全局唯一的,存放多个lua_State之间的一些共享数据

5,gc的一些管理和当前栈中upvalue的管理

6,错误处理的支持等等

C\C++和Lua拥有不同的数据类型,要实现两者之间的数据通信怎么办?Lua虚拟机提供Lua_State这样一种数据结构。任何一种数据从C\C++传入Lua虚拟机中,Lua都会将这类数据转换为一种通用的结构lua_TValue,并且将数据复制一份,将其压入虚拟栈中。lua_TValue定义如下:

  1. struct lua_TValue {  
  2.   TValuefields;  
  3. };  
  4.    
  5. #define TValuefields  \  
  6.     union { struct { Value v__; int tt__; } i; double d__; } u  
  7.    
  8. union Value {  
  9.   GCObject *gc;    /* collectable objects */ 
  10.   void *p; /* light userdata */ 
  11.   int b;   /* booleans */ 
  12.   lua_CFunction f; /* light C functions */ 
  13.   numfield /* numbers */ 
  14. }; 

Lua有自己的GC,C\C++由自己申请和释放内存,所以两者之间的内存管理是独立的。从C\C++中传递数据到Lua虚拟机会发生数据拷贝,从Lua虚拟机中传递出来是直接从虚拟栈中取值或者地址,所以数据从虚拟栈中pop之后,是否依然是有效引用需要额外注意。

 二,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得出。 

出栈操作:

API使用“索引”来引用栈中的元素,第一个压入栈的为1,第二个为2,依此类推。我们也可以使用负数作为索引值,其中-1表示为栈顶元素,-2为栈顶下面的元素,同样依此类推。

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而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型。

有关API的具体用法或者了解更多的API请访问其官方网站

原文出自:http://my.oschina.net/xlplbo/blog/314956

责任编辑:林师授 来源: xlplbo的博客
相关推荐

2010-01-20 09:32:30

C++类

2010-01-27 15:29:45

C++异常处理

2010-01-20 13:29:40

C++环境

2010-02-02 13:04:03

C++头文件

2010-01-20 10:49:29

Visual C++界

2010-01-19 14:39:22

C++ Builder

2010-01-12 09:59:08

Visual C++

2010-01-15 19:05:42

学习C++

2010-01-22 16:21:50

C++ Builder

2010-02-05 17:16:05

C++构造函数

2010-01-27 10:45:21

C++单例模式

2010-01-15 17:31:18

C++Test

2010-01-28 10:33:10

C++开发程序

2009-08-27 15:33:58

C# Cookie编程

2010-01-15 18:06:20

C++引用

2020-07-31 18:33:56

C++编程语言

2019-08-28 14:21:39

C++C接口代码

2013-12-13 16:53:00

Lua脚本语言C++

2016-09-14 21:44:50

JavascriptreactJsjsx

2010-01-22 18:06:24

C++代码
点赞
收藏

51CTO技术栈公众号