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++交互概要的更多相关文章

  1. Lua与C的交互

    Lua 与 C 的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  ...

  2. cocos2d-x lua与c++简单交互

    cocos2d-x lua与c++简单交互 version: cocos2d-x 3.6 本文讲述lua与c++的一些简单交互: lua通过消息方式调用c++无参接口 c++调用lua带参接口 1.通 ...

  3. Lua与C/C++交互问题

    初学lua,遇到注册C/C++交互函数问题 在lua与C/C++交互时,C/C++的注册Lua函数若是一个有返回类型(压栈)而不是获取类型的时候应该返回1而不是返回0,否则会出现在Lua中值为nil( ...

  4. Lua与C++的交互

    这篇文章说的挺详细的:Lua与C++的交互

  5. 通过lua栈了解lua与c的交互

    lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...

  6. Lua脚本和C++交互(一)

    现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或 ...

  7. Lua基本语法-lua与C#的交互(相当简单详细的例子)

    lua脚本 与 C#的交互 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Lua And C# -- ...

  8. lua和C++的交互(1)

    /* 以前听的一个故事,当年Java的创造者讲课的时候,一开始先拿一个简单的不能简单的小例子, 不断的扩展,最后成为一个复杂而完美的程序. 一个重要之重要的概念,就是栈.Lua与别的语言交互以及交换数 ...

  9. lua与c的交互(函数专用)

    Lua与C的交互 Lua是一个嵌入式的语言,它不仅可以是一个独立运行的程序,也可以是一个用来嵌入其它应用的程序库. C API是一个C代码与Lua进行交互的函数集,它由以下几部分构成: 1.  读写L ...

随机推荐

  1. Django 创建超级用户

    Django自带的后台管理是Django明显特色之一,可以让我们快速便捷管理数据.后台管理可以在各个app的admin.py文件中进行控制 #创建超级用户 python manage.py creat ...

  2. gei 操作

    git --version 查看版本号 进入项目文件 上传账号的用户名git config --global user.name "牛星宇" 上传账号的邮箱git config - ...

  3. TODO java 作业-梭哈--待完成

    作业:定义一个类,该类用于封装一桌梭哈游戏,这个类应该包含桌上剩下的牌的信息,并包含5个玩家的状态的信息,他们各自的位置,游戏状态(正在游戏或已放弃),手上已有的牌等信息.如果有可能,这个类还应该实现 ...

  4. maven pom添加本地jar,不提交私库

    <dependency> <groupId>taobao-sdk</groupId> <artifactId>taobaosdk</artifac ...

  5. (map string)Crazy Search hdu1381

    Crazy Search Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  6. BZOJ4698 差分 + 二分 + SA

    https://www.lydsy.com/JudgeOnline/problem.php?id=4698 题意:求N个字符串中最长的相同字串的长度,相同的定义是:两个子串长度相同且一个串的全部元素加 ...

  7. 如何在springcloud分布式系统中实现分布式锁?

    一.简介 一般来说,对数据进行加锁时,程序先通过acquire获取锁来对数据进行排他访问,然后对数据进行一些列的操作,最后需要释放锁.Redis 本身用 watch命令进行了加锁,这个锁是乐观锁.使用 ...

  8. falsk简单项目示例

    目录结构: 源码及分析 https://github.com/freshman411/Flask_test/

  9. JS事件委托应用场景

    给列表元素添加点击事件: 在javaScript中,添加到页面上的事件处理程序的数量,将直接关系到页面的整体运行性能. <li>标签的数量很大时,循环为每个子元素添加事件,绝非好方法. 有 ...

  10. Kafka技术内幕 读书笔记之(三) 消费者:高级API和低级API——消费者消费消息和提交分区偏移量

    消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块( FetchedDataChunk )放入分区信息的队列中 . 而每个队列都对应一个消息流( KafkaStream ),消费者客户 ...