C/C++ Lua通信
C/C++和Lua是如何进行通信的? http://www.luachina.cn/?post=38
2015-12-28
为了实现Lua和其他语言之间的通信,Lua虚拟机为C/C++提供了两个特性:
一,Lua_State状态机
lua_State主要是管理一个lua虚拟机的执行环境, 一个lua虚拟机可以有多个执行环境。Lua虚拟机通过维护这样一个虚拟栈来实现两种之间的通信,lua_State定义如下:
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而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型。
如何在Lua与C/C++之间实现table数据的交换 http://www.luachina.cn/?post=37
开始之前,明确几个问题,lua中的虚拟栈的索引编号问题(我们假设栈大小为n),编号1是栈底,n视栈顶,编号-1是栈顶,-n是栈底。lua中的库函数需要访问和操作栈上的数据都是通过索引编号定位的。但是我们需要明确一点,有些API并没有使用索引编号作为参数,意味着默认对栈顶进行操作。如lua_pushnumber(L, 66)将数值66压入栈顶,lua_tonumber(L, -1)取编号-1(栈顶)元素等等,如果这些基本知识和API的都已经熟悉了,那么lua与宿主之间的数据交换就很容易理解了。
姿势准备好了,那么问题来了。需求:我们现在要设计一个UI界面,我们希望这个UI是可以重用的。为了满足这个需求,显然我们必须将UI界面与显示数据分离。使用lua初始化数据后,将数据传递给UI界面然后显示。这样如果需求变更(游戏开发中经常产生这样的需求),我们也只需改变lua脚本就能重用UI界面,听上去真是程序猿的福音啊~~
用于显示UI的数据必定很多,需要使用lua中的table来封装这些数据,现在给定如下lua table数据:
我们的脚本将调用一个程序封装好的c API(TestTable函数),然后将tTest作为参数,压入虚拟栈中,如下:
需要说明的是在lua中tTest["gdp"]和tTest.gdp的调用形式是一样的,这是lua的语法糖。当然操作栈中的table方法除了lua_gettable和lua_settable还有其它方法,请参看lua_rawget和lua_rawset。理解栈中的元素变化是非常重要的。
LuaTestTable函数API的后面部分介绍了构造一个任意table作为返回值,返回给lua脚本。首先使用lua_newtable库函数新建一个table类型的数据,并压入栈。然后将键值对key-value依次压入栈,调用lua_settable(L, index)将key-value设置到table中,子table操作也是一样的(这里的index指的是要设置的table在栈中的索引编号)。
好了,基本介绍完了,最后来编写脚本,看看效果(以下是程序调用的脚本):
openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers https://github.com/openresty/lua-nginx-module#description
Lua | NGINX https://www.nginx.com/resources/wiki/modules/lua/
This module embeds Lua, via LuaJIT 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model.
Unlike Apache's mod_lua and Lighttpd's mod_magnet, Lua code executed using this module can be 100% non-blocking on network traffic as long as the Nginx API for Lua provided by this module is used to handle requests to upstream services such as MySQL, PostgreSQL, Memcached, Redis, or upstream HTTP web services.
用lua扩展你的Nginx(整理) - gccbuaa - 博客园 https://www.cnblogs.com/gccbuaa/p/7018287.html
原理
ngx_lua将Lua嵌入Nginx,能够让Nginx运行Lua脚本,而且高并发、非堵塞的处理各种请求。Lua内建协程。这样就能够非常好的将异步回调转换成顺序调用的形式。ngx_lua在Lua中进行的IO操作都会托付给Nginx的事件模型。从而实现非堵塞调用。开发人员能够採用串行的方式编敲代码,ngx_lua会自己主动的在进行堵塞的IO操作时中断。保存上下文;然后将IO操作托付给Nginx事件处理机制。在IO操作完毕后,ngx_lua会恢复上下文,程序继续运行,这些操作都是对用户程序透明的。
每一个NginxWorker进程持有一个Lua解释器或者LuaJIT实例,被这个Worker处理的全部请求共享这个实例。
每一个请求的Context会被Lua轻量级的协程切割,从而保证各个请求是独立的。 ngx_lua採用“one-coroutine-per-request”的处理模型。对于每一个用户请求,ngx_lua会唤醒一个协程用于执行用户代码处理请求,当请求处理完毕这个协程会被销毁。
每一个协程都有一个独立的全局环境(变量空间),继承于全局共享的、仅仅读的“comman data”。所以。被用户代码注入全局空间的不论什么变量都不会影响其它请求的处理。而且这些变量在请求处理完毕后会被释放,这样就保证全部的用户代码都执行在一个“sandbox”(沙箱),这个沙箱与请求具有同样的生命周期。 得益于Lua协程的支持。ngx_lua在处理10000个并发请求时仅仅须要非常少的内存。依据測试,ngx_lua处理每一个请求仅仅须要2KB的内存,假设使用LuaJIT则会更少。所以ngx_lua非常适合用于实现可扩展的、高并发的服务。
C/C++ Lua通信的更多相关文章
- 将硬件规定的通信协议用Lua实现(涉及到很多Lua通信的数据转换)
1:这次处理的是大唐的gps通信协议,先简单介绍一下他规定的通信规则: 信息结构: 传输说明: 信息结构中的各个字节书写时都是以十六进制标识,两位数组成.传输时,SOI和EOI(SOI=7EH,EOI ...
- cocos2d-x 使用Lua
转自:http://www.benmutou.com/blog/archives/49 1. Lua的堆栈和全局表 我们来简单解释一下Lua的堆栈和全局表,堆栈大家应该会比较熟悉,它主要是用来让C++ ...
- Lua与C
[前言] 对于Lua的基础总结总算告一段落了,从这篇博文开始,我们才真正的进入Lua的世界,一个无聊而又有趣的世界.来吧. Lua语言是一种嵌入式语言,它本身的威力有限:当Lua遇见了C,那它就展示了 ...
- lua 5.3 英文手册 google机器翻译版
LUA Lua 5.3参考手册作者:Roberto Ierusalimschy,Luiz Henrique de Figueiredo,Waldemar Celes 版权所有©2015-2018 Lu ...
- 高速掌握Lua 5.3 —— Lua与C之间的交互概览
Q:什么是Lua的虚拟栈? A:C与Lua之间通信关键内容在于一个虚拟的栈.差点儿全部的调用都是对栈上的值进行操作,全部C与Lua之间的数据交换也都通过这个栈来完毕.另外,你也能够使用栈来保存暂时变量 ...
- lua 与 c 的相互调用
Lua是一个嵌入式的语言,意味着Lua不仅可以是一个独立运行的程序包也可以是一个用来嵌入其他应用的程序库. Lua可以作为程序库用来扩展应用的功能,也就是Lua可以作为扩展性语言的原因所在.同时,Lu ...
- 怎样在Cocos2d-x中使用Lua脚本
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013321328/article/details/25699545 笔者使用的是Cocos2d-x ...
- Lua C++交互 应用实例步骤(UserData使用)
一.配置Lua C++交互环境 1.下载Lua 包环境 地址: https://www.lua.org/download.html ,我们这里用的是5.4.2版本. 2.新建C++ 控制台应用程序 3 ...
- fatal error LNK1104: 无法打开文件“lua51.lib”
今天学习C++与Lua通信,遇到了问题:fatal error LNK1104: 无法打开文件"lua51.lib" 开发环境: VS2012 cocos版本:cocos2d-x- ...
随机推荐
- Linux下删除文件名带有空格的文件
1.使用单引号将文件名括起来进行操作: rm '2018-08-07 17-29-48.png'
- [leetcode]114. Flatten Binary Tree to Linked List由二叉树构建链表
/* 先序遍历构建链表,重新构建树 */ LinkedList<Integer> list = new LinkedList<>(); public void flatten( ...
- Pytest测试框架(二):pytest 的setup/teardown方法
PyTest支持xUnit style 结构, setup() 和 teardown() 方法用于初始化和清理测试环境,可以保证测试用例的独立性.pytest的setup/teardown方法包括:模 ...
- Vue 面试题总结
1. Vue 框架的优点是什么? (1)轻量级框架:只关注视图层,大小只有几十Kb: (2)简单易学:文档通顺清晰,语法简单: (3)数据双向绑定,数据视图结构分离,仅需操作数据即可完 ...
- 关于领域驱动架构DDD思考
一个高大上的概念领域驱动架构就这样展开. 开发了多年的软件,一直以来的习惯是拿到产品的需求 对照UI的图纸然后就干干干 碰到问题大不了找人沟通再次定义问题,最后交付.其实最后也能把一件事情完成 但如果 ...
- 一次MySQL死锁的排查记录
前几天线上收到一条告警邮件,生产环境MySQL操作发生了死锁,邮件告警的提炼出来的SQL大致如下. update pe_order_product_info_test set end_time = ' ...
- Above the Median
http://www.forioi.com/p/3212 农夫约翰把他的N(1<=N<=1e5)奶牛排在一排来衡量他们的高度,牛i有:高度H_I(1<=H_I<=1e9)纳米– ...
- 接口的不同写法在Swagger上的不同
接口请求方法类型 (1) 如果接口没有指定请求的 method 类型,例如 GET.POST.PUT.DELETE 等. Swagger中 (2)指定了请求方法后 Swagger中就只有一个GET请求 ...
- Appium 介绍及环境安装
Appium是一个可用于测试iOS. Android操作系统和Windows桌面平台原生应用,移动网页应用和混合应用的自动化测试框架. 原生应用(Native App):用 android.iOS或者 ...
- 配置Oracle数据库和监听随Linux系统自启动【转】
配置Oracle数据库和监听随Linux系统自启动 在某些情况下需要在Linux操作系统上提供一种无人值守的随机启动Oracle的功能,目的也许仅仅是为了帮助那些对Oracle细节非常不关心 ...