lua与C/C++交互概要
转 http://blog.csdn.net/wildfireli/article/details/22307635
Lua生来就是为了和C交互的,因此使用C扩展Lua或者将Lua嵌入到C当中都是非常流行的做法。要想理解C和Lua的交互方式,首先要回顾一下C语言是如何处理函数参数的。
C函数和参数
大家知道C语言是用汇编实现的,在汇编语言中可没有函数的概念,与函数对应的是叫做子过程的东西,子过程就是一段指令,一个子过程与它调用的子过程之间通
过栈来进行参数的传递交互。在一个子过程在调用别的子过程之前,会按照约定的格式将要调用的子过程需要的参数入栈,在被调用的子过程中,可以按照约定的规
则将参数从栈中取出。同理,对于返回值的传递也同样是通过堆栈进行的。C语言约定的参数放入栈中的格式,就是“调用惯例”。C语言的函数原型则决定了压入
栈中的参数的数量和类型。
Lua的虚拟堆栈
Lua和C之间的交互巧妙的模拟了C语言的堆栈,Lua和C语言之间的相互调用和访问都通过堆栈来进行,巧妙的解决了不同类型之间变量相互访问的问题。具体的,我们想象如下一个图
+-------+ +-------+
| | | |
| | +-------+ | |
| C | <==> | | <==> | Lua |
| Space | |Virtual| | Space |
| | | Stack | | |
| | | | | |
+-------+ +-------+ +-------+
由于C和Lua是不同层次的语言,因此C语言的变量和Lua中的变量以及函数不能直接的交互,我们假定C语言和Lua都有自己的“空间(C Space和Lua Space)”。而这两个空间之间的交互就通过上图中的这个虚拟堆栈来解决。为何采用虚拟堆栈的方式来进行交互呢?其目的是在提供强大的灵活性的同时避免 交互时两种语言变量类型的组合爆炸。
C语言读写Lua全局变量(基本类型)
C语言读取Lua的全局变量是一种最简单的操作。通过上图我们可以猜测到,如果通过C语言读取Lua中的全局变量需要两步:1、将全局变量从Lua
Space压入虚拟堆栈;2、从堆栈将全局变量读取到C语言Space中。在Lua和C的交互中,Lua无法看到和操作虚拟堆栈,仅在C语言中有操作堆栈
的权利,因此前面说到的两步全都是在C语言中完成的。我们看一个简单的例子
Lua代码:
global_var1 = ;
print("Print global varb from lua", global_var1);
C代码:
void get_global(lua_State *L)
{
int global_var1;
lua_getglobal(L, "global_var1"); /* 从lua的变量空间中将全局变量global_var1读取出来放入虚拟堆栈中 */
global_var1 = lua_tonumber(L, -); /* 从虚拟堆栈中读取刚才压入堆栈的变量,-1表示读取堆栈最顶端的元素 */ printf("Read global var from C: %d\n", global_var1);
}
执行结果:
Lua中对堆栈的操作都是通过索引来进行的,索引为1表示从栈底数第一个元素,索引为2表示从栈底数第二个元素;同样也可以使用负数从栈顶开始计算,-1
表示从栈顶数第一个元素,-2表示从栈顶数第二个元素。更多堆栈的操作函数请参考lua的官方手册http://www.lua.org/manual
/5.2/manual.html。
同样从堆栈中获取元素,除了我们使用的lua_tonumber之外,还有lua_tolstring,lua_toboolean等。
通常情况下在读取变量之前还需要对堆栈中元素的实际类型做出检查:
void get_global(lua_State *L)
{
int global_var1;
lua_getglobal(L, "global_var1"); /* 从lua的变量空间中将全局变量global_var1读取出来放入虚拟堆栈中 */
if (!lua_isnumber(L, -)) /* 检查堆栈中栈顶第一个元素是否是数字 */
error(L, "Is not number.");
global_var1 = lua_tonumber(L, -); /* 从虚拟堆栈中读取刚才压入堆栈的变量,-1表示读取堆栈最顶端的元素 */
}
写入全局变量也一样简单: 首先将数据压入堆栈,然后再将堆栈中的数据存入全局变量。
C代码:
void set_global(lua_State *L)
{
lua_pushinteger(L, );
lua_setglobal(L, "global_var1");
printf("set global var from C:9\n");
}
cococs C++--------------------------------------------------------------------------------与Lua
虽然终极方法是用bindings-generator脚本来注册C++类进Cocos2d-x的Lua环境,但理解toLua++本身的用法还是狠有必要的,只有知道了toLua++原本的用法,才能更好地理解Cocos2d-x是怎么把自己的C++类都注册进Lua环境的,这不仅能让编程时的思路更加 清晰,也能为日后在源码中寻找各种接口文档的过程中不至于看不懂那一大堆tolua_beginmodule、tolua_function是什么 意思。影响程序员学习提高的一大障碍就是忽略那些一知半解的代码,不去刨根究底地搞明白。
使用toLua++的标准做法是:
1、准备好自己的C++类,该怎么写就怎么写
2、仿造这个类的.h文件,改一个.pkg文件出来,具体格式要按照toLua++的规定,比如移除所有的private成员等
3、建一个专门用来桥接C++和Lua之间的C++类,使用特殊的函数签名来写它的.h文件,.cpp文件不写,等着toLua++来生成
4、给这个桥接的C++类写一个.pkg文件,按照toLua++的特殊格式来写,目的是把真正做事的C++类给定义进去
5、在命令行下用toLua++生成桥接类的.cpp文件
6、程序入口引用这个桥接类,执行生成的桥接函数,Lua环境中就可以使用真正做事的C++类了
编译---------------------------------------
在LUA的官网下载LUA源码后会有SRC文件夹
其中 lua.c 和 luac.c 都有 int main 函数,各源文件从根节点互相引用,可以将其编译为库 或 .exe使用,或将源码添加到项目里(要放到根目录)。
lua.c的main是编译运行时用的
luac.c的main是编译一个将lua代码编译成二进制代码的软件用的
luaconf.h 有个 LUA_BUILD_AS_DLL 用于编译windows动态链接库.dll文件
lua与C/C++交互概要的更多相关文章
- Lua与C的交互
Lua 与 C 的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1. ...
- cocos2d-x lua与c++简单交互
cocos2d-x lua与c++简单交互 version: cocos2d-x 3.6 本文讲述lua与c++的一些简单交互: lua通过消息方式调用c++无参接口 c++调用lua带参接口 1.通 ...
- Lua与C/C++交互问题
初学lua,遇到注册C/C++交互函数问题 在lua与C/C++交互时,C/C++的注册Lua函数若是一个有返回类型(压栈)而不是获取类型的时候应该返回1而不是返回0,否则会出现在Lua中值为nil( ...
- Lua与C++的交互
这篇文章说的挺详细的:Lua与C++的交互
- 通过lua栈了解lua与c的交互
lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...
- Lua脚本和C++交互(一)
现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或 ...
- Lua基本语法-lua与C#的交互(相当简单详细的例子)
lua脚本 与 C#的交互 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Lua And C# -- ...
- lua和C++的交互(1)
/* 以前听的一个故事,当年Java的创造者讲课的时候,一开始先拿一个简单的不能简单的小例子, 不断的扩展,最后成为一个复杂而完美的程序. 一个重要之重要的概念,就是栈.Lua与别的语言交互以及交换数 ...
- lua与c的交互(函数专用)
Lua与C的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1. 读写L ...
随机推荐
- 如何 通过 userAgent 区别微信小程序
微信内置浏览器: 微信小程序: 有micromessenger是微信内置浏览器,有micromessenger和miniprogram的是微信小程序. (ios不适用) if(navigator.u ...
- navicat primium 快捷键与命令
1.ctrl+q 打开查询窗口 2.ctrl+/ 注释sql语句 3.ctrl+shift +/ 解除注释 4.ctrl+r 运行查询窗口的s ...
- js jquery 判断元素是否在数组内
js jquery 判断元素是否在数组内 一,js方法 var arr = ["a", "b", "c"]; // js arr.index ...
- RAP 接口Mock示例
前后端分离式开发的思考 目前大部分公司都实行了前后端分离开发.然而在项目开发过程当中,经常会遇到以下几个尴尬的场景: 1.前端开发依赖于后端接口数据,需要与后端接口联调才能获得数据展示,从而拖慢了开发 ...
- io系列之常用流一
一. 读取键盘录入和数据打印 在System类中, System.out: 对应的是标准输出设备(控制台)(一个PrintStream). System.in: 对应的是标准输入设备(键盘)(一个In ...
- google chrome 浏览器书签丢失问题
在一次新打开标签页时,电脑卡死,强制重启后打开google chrome 浏览器,发现历史什么的都在,但书签栏全部丢失了 找到 系统盘:\Users\用户名\AppData\Local\Google\ ...
- 2017-12-15python全栈9期第二天第七节之数字转换成布尔值
#!/user/bin/python# -*- coding:utf-8 -*-print(bool(2))
- flask blueprint
在使用flask进行一个项目编写的时候,可能会有许多个模块,如一个网站的前台(home)和后台(admin)模块,如果把这两个模块都放在一个views.py文件之中,那么最后views.py文件必然臃 ...
- 面向对象【day08】:异常处理-断言(七)
本节内容 1.概述 2.知识点回顾 3.断言 一.概述 python中断言,这个我是第一次听说到的,断言有什么用呢?断言就是做一些程序的检查工作,就是在执行之前需要做的一些检查,比如类似于安检一样,合 ...
- Mybatis笔记一:写一个demo
什么是Mybatis? 在Java中,我们连接数据库可以使用最初级的JDBC,但是这样很麻烦,每次都要写好多,所以Mybatis出现了,Mybatis可以帮我们很简单很简单的实现与数据库的读取改写操作 ...