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

简介:

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

   lua_State主要是管理一个lua虚拟机的执行环境, 一个lua虚拟机可以有多个执行环境。Lua虚拟机通过维护这样一个虚拟栈来实现两种之间的通信,lua_State定义如下:
struct lua_State {
  CommonHeader;
  lu_byte status;
  StkId top;  /* first free slot in the stack */
  global_State *l_G;
  CallInfo *ci;  /* call info for current function */
  const Instruction *oldpc;  /* last pc traced */
  StkId stack_last;  /* last free slot in the stack */
  StkId stack;  /* stack base */
  int stacksize;
  unsigned short nny;  /* number of non-yieldable calls in stack */
  unsigned short nCcalls;  /* number of nested C calls */
  lu_byte hookmask;
  lu_byte allowhook;
  int basehookcount;
  int hookcount;
  lua_Hook hook;
  GCObject *openupval;  /* list of open upvalues in this stack */
  GCObject *gclist;
  struct lua_longjmp *errorJmp;  /* current error recover point */
  ptrdiff_t errfunc;  /* current error handling function (stack index) */
  CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
};
    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定义如下:
struct lua_TValue {
  TValuefields;
};

#define TValuefields  \
    union { struct { Value v__; int tt__; } i; double d__; } u

union Value {
  GCObject *gc;    /* collectable objects */
  void *p;         /* light userdata */
  int b;           /* booleans */
  lua_CFunction f; /* light C functions */
  numfield         /* numbers */
};
   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而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型。

文章转载自 开源中国社区 [http://www.oschina.net]

相关文章
|
1月前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
|
5月前
|
存储 Cloud Native Linux
C++封装了socket通信类
C++封装了socket通信类
|
5月前
|
C++
C++实战-仿QQ项目终端版通信
C++实战-仿QQ项目终端版通信
37 0
|
2月前
|
C++
C++实现Socket连接通信
C++实现Socket连接通信
13 1
|
7月前
|
数据安全/隐私保护 C++ Python
Qt RSA OpenSSL C++ Qt加密解密签字通信系统窗体源码
Qt RSA OpenSSL C++ Qt加密解密签字通信系统窗体源码
130 0
Qt RSA OpenSSL C++ Qt加密解密签字通信系统窗体源码
|
7月前
|
数据安全/隐私保护 C++ 计算机视觉
C++ RSA加密解密签字通信系统源码
C++ RSA加密解密签字通信系统源码
90 0
C++ RSA加密解密签字通信系统源码
|
8月前
|
网络协议 Linux C++
Linux TCP作为服务器连接的单连接、Select、Poll和Epoll方式:C/C++实现高效的服务器通信
在Linux服务器开发中,TCP(Transmission Control Protocol)作为面向连接的通信方式,为实现可靠的服务器通信提供了强大支持。不同的服务器连接方式,如单连接、Select、Poll和Epoll,各有优势,可以根据连接数和性能需求选择合适的方式。本文将深入探讨这四种方式的实现原理,并给出C/C++代码例子,帮助读者更好地理解和使用这些方式。
117 0
|
10月前
|
Ubuntu 云计算 C++
C++与lua的结合,LuaBridge的使用及遇到的坑
C++与lua的结合,LuaBridge的使用及遇到的坑
|
11月前
|
C++
[✔️]lua中的function,在c++进行callback
[✔️]lua中的function,在c++进行callback
135 0
|
11月前
|
C++
[✔️]c++返回2个值给lua,tolua如何处理c++函数重载
[✔️]c++返回2个值给lua,tolua如何处理c++函数重载
90 0