Lua和C之间的交互
转自:http://blog.csdn.net/sumoyu/article/details/2592693
(一) Lua 调C函数
- 什么样类型的函数可以被Lua调用
- typedef int (*lua_CFunction) (lua_State *L);
- 符合类型的函数怎样处理后才可以被Lua调用
使用lua_register或者 lua_pushfunction和lua_setglobal()把要调用的函数加入到lua状态机中。
- #define lua_register(L,n,f) /
- (lua_pushcfunction(L, f), lua_setglobal(L, n))
lua_register的第二个参数就是Lua脚本中对这个函数的调用名称。
举例:
如果C函数名称是foo,使用lua_registe注册(L,”acfoo”,foo),那么在Lua脚本中使用acfoo来表示使用foo函数.
- Lua 如何调用c函数
简单,使用注册的名称直接调用
- 如何传递参数和计算结果
① 使用堆栈交互
引用使用手册上的一段话:
Lua 使用一个虚拟栈来和 C 传递值。栈上的的每个元素都是一个 Lua 值(nil,数字,字符串,等等)。
无论何时 Lua 调用 C,被调用的函数都得到一个新的栈,这个栈独立于 C 函数本身的堆栈,也独立于以前的栈。(在 C 函数里,用 Lua API 不能访问到 Lua 状态机中本次调用之外的堆栈中的数据),它里面包含了 Lua 传递给 C 函数的所有参数,而 C 函数则把要返回的结果也放入堆栈以返回给调用者。
方便起见,所有针对栈的 API 查询操作都不严格遵循栈的操作规则。而是可以用一个索引来指向栈上的任何元素:正的索引指的是栈上的绝对位置(从一开始);负的索引则指从栈顶开始的偏移量。更详细的说明一下,如果堆栈有 n 个元素,那么索引 1 表示第一个元素(也就是最先被压入堆栈的元素)而索引 n 则指最后一个元素;索引 -1 也是指最后一个元素(即栈顶的元素),索引 -n 是指第一个元素。如果索引在 1 到栈顶之间(也就是,1 ≤ abs(index) ≤ top)我们就说这是个有效的索引。
② 从Lua脚本中获取参数
- int n = lua_gettop(L);
- /* get each argument */
- lua_tostring(lua_State *L, int index)
- …….
index: 1—左边第一个参数,2—左边第二个参数,......
③ 返回返回值
按顺序返回,Lua按照返回顺序接受
Lua_pushXXX(L,第一个返回值)
Lua_pushXXX(L,第二个返回值)
………
Lua调用C函数例子:
C程序:
- static int average(lua_State *L)
- {
- /* get number of arguments */
- int n = lua_gettop(L);
- double sum = ;
- int i;
- /* loop through each argument */
- for (i = ; i <= n; i++)
- {
- if (!lua_isnumber(L, i))
- {
- lua_pushstring(L, "Incorrect argument to 'average'");
- lua_error(L);
- }
- /* total the arguments */
- sum += lua_tonumber(L, i);
- }
- /* push the average */
- lua_pushnumber(L, sum / n); //第一个返回值
- /* push the sum */
- lua_pushnumber(L, sum); //第二个返回值
- /* return the number of results */
- return ;
- }
- void LuaCallC()
- {
- /* initialize Lua */
- lua_State * L = lua_open();
- /* load Lua base libraries */
- luaL_openlibs(L);
- /* register our function */
- lua_register(L, "average", average);
- /* run the script */
- luaL_dofile(L, "average.lua");
- /* cleanup Lua */
- lua_close(L);
- }
Lua脚本,average.lua:
- avg, sum = average(,,,,)
- print("The average is ", avg)
- print("The sum is ", sum)
(二) Lua 从C库中调用
- 生成C函数库
① 所有可以被Lua调用的函数必须是lua_CFunction类型
② 所有被调用的函数加入到一个luaL_reg数组中
③ 一个luaopen_*(*表示库的名称)供lu调用库时打开库
使用luaL_register(lua_State *L,
const char *libname,
const luaL_Reg *l)
libname,注册lua使用这个库时的使用名称
luaL_Reg *l,把luaL_Reg数组里的函数注册到lua栈里,供lua调用
注意:BCB默认导出的c函数前面加了下划线,因此在动态库工程中加入一个def文件,在生成时不用加下划线。内容是:
Export
FunName = _FunName (FunName表示要导出的函数名称,Lua使用的库中就是luaopen_*)
- Lua使用c库
require(libname) – 打开使用的库
libname.FunName – 使用c库中提供的函数
Lua调用C函数库例子:
C库代码,C函数的名称”dllforlua.dll”
- static int lua_msgbox(lua_State* L)
- {
- const char* message = luaL_checkstring(L, );
- const char* caption = luaL_optstring(L, , "");
- int result = MessageBox(NULL, message, caption, MB_YESNO);
- lua_pushnumber(L, result);
- return ;
- }
- static const luaL_Reg mylib[] =
- {
- {"msgbox", lua_msgbox},
- {NULL, NULL}
- };
- int __declspec(dllexport) luaopen_dllforlua(lua_State* L)
- {
- luaL_register(L, "dllforlua", mylib);
- return ;
- }
Lua脚本,Test.lua
- require(“dllforlu”)
- dllforlua.msgbox("Hey, it worked!", "Lua Message Box");
(三) C调Lua 函数
- 初始化Lua环境
Lua_open或者:lua_newstate
luaL_newstate(调用lua_newstate,并且设置了一个恐慌函数)
- 加载Lua标准库
Lua_openlibs(打开所有标准库)
不打开所有库,打开需要的库:
Luaopen_base
luaopen_package
luaopen_string
luaopen_table
luaopen_math
……….
- 加载Lua和函数函数
luaL_dofile()
lua_getglobal()
大小写敏感,名字于Lua脚本的函数名称大小写完全一致
- 压入参数
不同类型采用不同的函数,按照从左往右的顺序依次压栈
lua_pushnumber,lua_pushstring,…..
- 执行函数
lua_call, lua_pcall
- 获取返回值
不同类型使用不同的函数,注意索引,获取前要检查类型
- 从栈中弹出返回值
lua_pop()
- 关闭Lua状态机
lua_close()
C程序掉用Lua函数例子:
C函数:
- void CCallLua()
- {
- // Create a LUA VMachine
- lua_State *L;
- //L = luaL_newstate();
- L = lua_open();
- //Load Libraries
- luaL_openlibs(L);
- // 运行脚本 /
- luaL_dofile(L, "clua.lua");
- lua_getglobal(L,"Sum");
- lua_pushnumber(L,);//第一个参数
- lua_pushnumber(L,);//第二个参数
- lua_pushnumber(L,);//第三个参数
- lua_pcall(L,,,);
- double sum=,ave=;
- if(lua_isnumber(L,))
- {
- sum=lua_tonumber(L,);
- }
- if(lua_isnumber(L,))
- {
- ave=lua_tonumber(L,);
- }
- lua_pop(L,);
- cout<<"Sum ="<<sum
- <<"/nAve ="<<ave<<endl;
- // 清除Lua
- lua_close(L);
- getchar();
- }
Lua脚本Clua.lua:
- function Sum(...)
- local s=
- local num=
- for k,v in pairs{...} do
- s = s + v
- num = k
- end
- return s,s/num
- end
Lua和C之间的交互的更多相关文章
- 高速掌握Lua 5.3 —— Lua与C之间的交互概览
Q:什么是Lua的虚拟栈? A:C与Lua之间通信关键内容在于一个虚拟的栈.差点儿全部的调用都是对栈上的值进行操作,全部C与Lua之间的数据交换也都通过这个栈来完毕.另外,你也能够使用栈来保存暂时变量 ...
- Lua和C语言的交互——C API
Lua可作为扩展性语言(Lua可以作为程序库用来扩展应用的功能),同时也是个可扩展的语言(Lua程序中可以注册由其他语言实现的函数). C和Lua交互的部分称为C API.C API是一个C代码与Lu ...
- 我的Android第五章:通过Intent实现活动与活动之间的交互
Intent在活动的操作 作用: Itent是Android程序中各个组件直接交换的一个重要方式可以指定当前组件要执行任务同时也可以给各个组件直接进行数据交互 同时Inten ...
- Fragments之间的交互(实现参数传递)
Fragments之间的交互(实现参数传递) 日常开发中,通常Fragments之间可能需要交互,比如基于用户事件改变Fragment的内容.所有Fragment之间的交互需要通过他们关联的Activ ...
- AngularJs-指令和指令之间的交互(动感超人)
前言: 上节我们学习到了指令和控制器之间的交互,通过给指令添加动作,调用了控制器中的方法.本节我们学习指令和指令之间是如何交互的,我们通过一个小游戏来和大家一起学习,听大漠老师说这是国外的人写的dem ...
- OC和JS之间的交互
OC和JS之间的交互 目录 对OC和JS之间交互的理解 JS调用OC OC调用JS 对OC和JS之间交互的理解 JS调用OC JS文件 function sendCommand(cmd,param){ ...
- 安卓任意两个或多个Fragment之间的交互与刷新界面
平时项目中遇到一个问题:在子fragment中刷新父fragment的界面,通俗的说也就是在任何一个fragment中来刷新另一个fragment.大家都知道activity和fragment之间的交 ...
- WPF自学入门(八)WPF窗体之间的交互
今天我们一起来看一下WPF窗体之间的交互-窗体之间的传值.有两个窗体,一个是父窗体,一个是子窗体.要将父窗体的文本框中的值传递给子窗体中的控件.我们该怎么实现? 接下来我们一起来实现窗体之间的传值,在 ...
- python 全栈开发,Day18(对象之间的交互,类命名空间与对象,实例的命名空间,类的组合用法)
一.对象之间的交互 现在我们已经有一个人类了,通过给人类一些具体的属性我们就可以拿到一个实实在在的人.现在我们要再创建一个狗类,狗就不能打人了,只能咬人,所以我们给狗一个bite方法.有了狗类,我们还 ...
随机推荐
- Developing a plugin framework in ASP.NET MVC with medium trust
http://shazwazza.com/post/Developing-a-plugin-framework-in-ASPNET-with-medium-trust.aspx January 7, ...
- gdb命令与调试方法
单线程 http://www.cnblogs.com/lidabo/p/5629830.html 编译程序一定要加-g选项 gcc -g test.c -o test 进入gdb调试:gdb 程序名 ...
- 导出Excel之Epplus使用教程3(图表设置)
导出Excel之Epplus使用教程1(基本介绍) 导出Excel之Epplus使用教程2(样式设置) 导出Excel之Epplus使用教程3(图表设置) 导出Excel之Epplus使用教程4(其他 ...
- 利用ADSL拨号上网方式如何搭建服务器
序:搭建服务器需要两个条件硬件服务器和固定公网IP,随便一台个人电脑都可以作为硬件服务器,就剩下一个问题,如何获得一个固定公网IP. 第一章 扫盲:ADSL拨号上网方式,本地IP与公网IP的区别 一. ...
- Unity 利用NGUI做屏幕分辨率适配+学习UIDraggablePanel的使用
原地址:http://blog.sina.com.cn/s/blog_697b1b8c0101g2r4.html 大家使用unity,一定有看中其跨平台的强大功能,因此也难免会遇到不同屏幕分辨率适配的 ...
- [Educational Codeforces Round 16]D. Two Arithmetic Progressions
[Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...
- HDU 2897
Problem Description 当日遇到月,于是有了明.当我遇到了你,便成了侣. 那天,日月相会,我见到了你.而且,大地失去了光辉,你我是否成侣?这注定是个凄美的故事.(以上是废话) 小t和所 ...
- python 异步线程简单实现
import threading def foo(): with open(r'./result.log','wb') as f: f.write('=some logs here ==') t = ...
- C#中Const和Readonly的区别
const 的概念就是一个包含不能修改的值的变量.常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量.如果 const int a = b+1;b是一个变量,显然不能再 ...
- ASP.NET MVC 入门系列教程
ASP.NET MVC 入门系列教程 博客园ASP.NET MVC 技术专题 http://kb.cnblogs.com/zt/mvc/ 一个居于ASP.NET MVC Beta的系列入门文章,有朋友 ...