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方法.有了狗类,我们还 ...
随机推荐
- js中test()函数在正则中使用
test() 方法用于检测一个字符串是否匹配某个模式. 返回一个 Boolean 值,它指出在被查找的字符串中是否匹配给出的正则表达式. regexp.test(str) 参数 regexp 必选项. ...
- 编写自己的Acunetix WVS漏洞扫描脚本详细教程
AWVS提供了自定义的脚本编程接口,可是网上的资料很少,只有官方的几篇介绍和参考手册,最近研究了一下怎么编写AWVS的漏洞脚本来写一篇简单性的文章 本文以8.0为例,首先呢安装好Acunetix We ...
- .NET设计模式(2):单件模式(Singleton Pattern)(转载)
概述 Singleton模 式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程 序在调用某一个类时,它是不 ...
- ASP.NET MVC 开启AJAX跨域请求
<system.webServer> <httpProtocol> <customHeaders> <add name="Access-Contro ...
- 利用nginx向现有网站添加登录验证功能(不添加修改现有网站代码)
在不改变现有网站代码的前提下加入验证功能: 1.假设现有网站后端nodejs,端口3000,nginx配置如下 server { listen 80; server_name localhost; l ...
- Marriage Ceremonies(状态压缩dp)
Marriage Ceremonies Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu ...
- Eighth scrum meeting - 2015/11/2
由于之前的在线视频播放控件功能过于简单,我们今天从网上找了一个效果还不错的视频播放开源项目,在添加了复杂的依赖后终于能够正常使用了,效果比起之前来也好了很多,而且后续的视频下载功能也可以基于这个来开发 ...
- QEMU-KVM中的多线程压缩迁移技术
导读 目前的迁移技术,都是通过向QEMUFILE中直接写入裸内存数据来达到传送虚拟机的目的端,这种情况下,发送的数据量大,从而会导致更高的迁移时间(total time)和黑宕时间(downtime) ...
- myeclipse2014破解过程
之前装的是10,后来没事试试装了2014,然后再破解2014后发现2010的证书就失效了,之前在网上也没找到方法,这段时间也没管,今天又自己想办法试了试,发现成功了!下边是我在网上找的破解方法的破解步 ...
- The server does not support version 3.0 of the J2EE Web module specification
1.错误: 在eclipse中使用run->run on server的时候,选择tomcat6会报错误:The server does not support version 3.0 of t ...