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 ...
随机推荐
- JQuery选择器,事件,DOM操作,动画
JQuery是一个JavaScript代码库,或者是JavaScript框架: 1.选择器:(和CSS选择器一致) 基本选择器:ID选择器$('#div1');Class选择器('.div1');标签 ...
- P1024 一道naive的二分
好吧,这道题思路还是比较简单的.整个程序大体上很快就打出来了,然后修改了解为整数的情况. 但是交上去一直是50分,最后我很无耻的看了题解,然后抄了一个玄学if回来,瞬间AC,不知道为什么... 这句就 ...
- Appium的图像界面浅说
appium的图形用户界面(GUI) (1)Application中各个项的含义作用: Application Path:填写你需要测试的Android APK的包地址(两种方式:1直接点击Choos ...
- 第十九节,使用RNN实现一个退位减法器
退位减法具有RNN的特性,即输入的两个数相减时,一旦发生退位运算,需要将中间状态保存起来,当高位的数传入时将退位标志一并传入参与计算. 我们在做减法运算时候,把减数和被减数转换为二进制然后进行运算.我 ...
- GitLab 环境搭建【CentOS7】
RPM安装方式 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7 [最好给服务器分配至少4G内存] 先检查一下依赖:sshd [root@l ...
- PHP实现异步处理
resource fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, ...
- 【清北学堂2018-刷题冲刺】Contest 1
Task 1:最小公倍数 输入n,求n与246913578的最小公倍数. 结果对1234567890取模. [样例输入] 3 [样例输出] 246913578 [数据规模和约定] 对于30%的数据 ...
- (BFS/DFS) leetcode 200. Number of Islands
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...
- C# 实现身份验证之WebApi篇
今天再来总结关于如何实现WebApi的身份验证,以完成该系列所有文章,WebApi常见的实现方式有:FORM身份验证.集成WINDOWS验证.Basic基础认证.Digest摘要认证 第一种:FOR ...
- Java父类与子类方法调用顺序
父类 FatherClass package 父类与子类方法调用顺序; /** * 父类 * @author shundong * */ public class FatherClass { priv ...