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

如有任何疑问和建议,欢迎指出讨论,谢谢~

时间: 2014-09-16

vc++实现的tcp socket客户端和服务端示例

Tcp Server 复制代码 代码如下: #include <WinSock2.h>#include <stdio.h> #pragma comment(lib, "ws2_32.lib") int main(){ // initial socket library WORD wVerisonRequested; WSADATA wsaData; int err; wVerisonRequested = MAKEWORD(1, 1); err = WSASta

深入分析Visual C++进行串口通信编程的详解

利用Visual C++在windows环境下设计异步串行通信程序可以使用不同的方法.一种方法可以使用windows系统提供的串行口API函数:另一种方法可以直接使用Microsoft公司提供的ActiveX控件MSCOMM.OCX.利用MSCOMM.OCX控件进行串行口程序设计相对比较简单,只要对该控件的属性.事件和方法进行设置和操作,就能完成简单的串行通信功能.而直接使用windows系统提供的串行口API函数则相对较为灵活.试验中,可根据自己的情况任意其中一种进行编程.以下针对如何使用wi

C++广播通信实例

本文实例讲述了C++实现广播通信的方法.分享给大家供大家参考.具体实现方法如下: 广播通信代码框架: 1. 协议都是: 复制代码 代码如下: SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0); 2. 服务端设置选项 复制代码 代码如下: BOOL bBroadcast = TRUE;  ::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL)); 3. 服务端向255

C++实现获取IP、子网掩码、网关、DNS等本机网络参数的方法

本文以一个完整实例形式介绍了C++实现获取IP.子网掩码.网关.DNS等本机网络参数的方法,供大家参考,具体的完整实例如下: #pragma comment(lib,"Ws2_32.lib") #include <Iphlpapi.h> #pragma comment(lib, "Iphlpapi.lib") using namespace std; typedef struct tagNetworkCfg { char szIP[18]; char s

Android 模拟器(JAVA)与C++ socket 通讯 分享

C++ 作为Client端view plaincopy to clipboardprint? 复制代码 代码如下: // Client.cpp : Defines the entry point for the console application.     //     #include "stdafx.h"     #include      #pragma comment(lib,"ws2_32.lib")     #define  MAX_BUF_SIZE

C++设置系统时间及系统时间网络更新的方法

本文实例讲述了C++设置系统时间及系统时间网络更新的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: //根据返回的时间设置系统时间 void setTimeFromTP(ULONG ulTime) {      FILETIME ft;      SYSTEMTIME st;        //将基准时间转换成windows文件时间      st.wYear = 1900;      st.wMonth = 1;      st.wDay = 1;      st.wHo

Lua和C++的通信流程代码实例

上一章传送门:http://www.jb51.net/article/55088.htm 本章我们来学习一个小Demo,也就是上一章中的场景:C++从Lua中获取一个全局变量的字符串. 1. 引入头文件 我们来看看要在C++中使用Lua,需要些什么东西 复制代码 代码如下: /*    文件名:    HelloLua.h    描 述:    Lua Demo    创建人:    笨木头    创建日期:   2012.12.24 */ #ifndef __HELLO_LUA_H_ #def

Lua和C++的通信流程分解

网上关于Lua的教程似乎还没有泛滥,最近刚好学习在Cocos2d-x使用Lua,当然了,我是写教程狂,我会分享我的学习心得的~ (旁白:我噗~!每次你写东西我就要吐槽,你不累么= =)   这是第一课,先来让Lua和C++认识一下,顺便让它们逛街吃饭牵小手什么的- (旁白:...吹,继续吹) 1. Lua的堆栈和全局表 我们来简单解释一下Lua的堆栈和全局表,堆栈大家应该会比较熟悉,它主要是用来让C++和Lua通信的,是的,它们并不认识对方,只能通过堆栈来沟通,就像写信一样. (旁白:它们不会用

Android使用http协议与服务器通信的实例

网上介绍Android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及.因此,自己对此做了些总结,给出了我的一个解决方案. 首先,需要明确一下http通信流程,Android目前提供两种http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较适合上传/下载文件,HttpClient相对来讲更大更全能,但是速度相

JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序

以及需要用到Http方式和Openfire通信的第三方库(JabberHTTPBind). JabberHTTPBind是jabber提供的XMPP协议通信的Http bind发送的形式,它可以完成WebBrowser和Openfire建立长连接通信. 主要通信流程如下图所示: 用户A通过JavaScript jsjac.js库发送一条消息到JabberHTTPBind这个Servlet容器,然后JabberHTTPBind的Servlet容器会向Openfire发送XMPP协议的XML报文.O

python之Socket网络编程详解

什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在计算机领域中,网络是信息传输.接收.共享的虚拟平台,通过它把各个点.面.体的信息联系到一起,从而实现这些资源的共享.网络是人类发展史来最重要的发明,提高了科技和人类社会的发展. 网络通信的三要素 IP地址 用来表示一台独立的主机 特殊的IP地址 127.0.0.1或称localhost(表示本地回环

在当前Activity之上创建悬浮view之WindowManager悬浮窗效果

最近有学生做毕业设计,想使用悬浮窗这种效果,其实很简单,我们可以通过系统服务WindowManager来实现此功能,本章我们来试验一下在当前Activity之上创建一个悬浮的view. 第一步:认识WindowManager 这个接口用于与 window manager (窗口管理器, 应用框架层) 进行交互. 通过getSystemService(Context.WINDOW_SERVICE)可以获取到WM的实例. 继承关系 public interface WindowManager imp

在Spring Boot中实现HTTP缓存的方法

缓存是HTTP协议的一个强大功能,但由于某些原因,它主要用于静态资源,如图像,CSS样式表或JavaScript文件,但是,HTTP缓存不仅限于这些,还可以将其用于动态计算的资源. 通过少量工作,您可以加快应用程序并改善整体用户体验.在本文中,您将学习 如何使用内置的HTTP响应缓存机制来实现缓存SpringBoot控制器的结果 . 1.如何以及何时使用HTTP响应缓存? 您可以在应用程序的多个层上进行缓存.数据库具有其缓存存储,Web客户端也在其需要重用的信息.HTTP协议负责网络通信.缓存机

微信小程序渲染性能调优小结

网页的性能优化是前端开发老生常谈的热门话题,其中微信小程序因其页面双线程架构设计,所以性能优化的手段跟传统的 H5 应用不太一样.今天主要介绍一下微信小程序页面双线程架构的特性给页面渲染带来的一些影响,以及应对的一些渲染性能调优策略.为了叙述方便,下文会把微信小程序简称为小程序. 小程序的双线程架构 与传统的浏览器Web页面最大区别在于,小程序的是基于 双线程 模型的,在这种架构中,小程序的渲染层使用 WebView 作为渲染载体,而逻辑层则由独立的 JsCore 线程运行 JS 脚本,双方并不

Android蓝牙聊天开源项目

前言 基于Android Classic Bluetooth的蓝牙聊天软件,目前仅支持一对一实时通信.文件传输.好友添加.好友分组.好友在线状态更新等功能,其中消息发送支持文本.表情等方式. 项目地址:Android蓝牙聊天项目 前景 蓝牙技术作为一种小范围无线连接技术,能够在设备间实现方便快捷.灵活安全.低成本.低功耗的数据和语音通信,是目前实现无线个人局域网的主流技术之一.同时,蓝牙系统以自组式组网的方式工作,每个蓝牙设备都可以在网络中实现路由选择的功能,可以形成移动自组网络.蓝牙的特性在许

Docker跨主机网络(manual)的实现

1. Macvlan 简介 在 Macvlan 出现之前,我们只能为一块以太网卡添加多个 IP 地址,却不能添加多个 MAC 地址,因为 MAC 地址正是通过其全球唯一性来标识一块以太网卡的,即便你使用了创建 ethx:y 这样的方式,你会发现所有这些"网卡"的 MAC 地址和 ethx 都是一样的,本质上,它们还是一块网卡,这将限制你做很多二层的操作.有了 Macvlan 技术,你可以这么做了. Macvlan 允许你在主机的一个网络接口上配置多个虚拟的网络接口,这些网络 inter