lua与c#交互,c调用lua函数
Lua语言和C/C集成的调查总结HZQHBC专栏-博客频道-CSDN。网
Lua语言与C/C集成研究综述
分类:
左上臂
C
2012-04-28 10:48
十个人读书。
评论(0)
收集
原报道转自http://bbs.luaer.cn/read-Lua-tid-58-fpage-4.html1. Lua的特色
Lua是一种小型脚本语言。作者是巴西人。该语言旨在嵌入应用程序,从而为应用程序提供灵活的扩展和定制功能。它的主页是
www.lua.org .
Lua最著名的应用是在暴雪的网络游戏WOW中。
Lua脚本可以方便地被C/C代码调用,也可以反过来调用C/C函数,这使得Lua在应用中得到广泛应用。不仅作为扩展脚本,而且作为一个通用的配置文件,而不是XML,Ini等文件格式,而且更容易理解和维护。
Lua用标准C编写,代码简洁美观,几乎可以在所有操作系统和平台上编译运行。一个完整的Lua解释器才200k,Lua是目前所有脚本引擎中最快的。这些都决定了Lua作为嵌入式脚本是最好的选择。
Lua有一个同步JIT项目,在特定平台上提供即时编译,这会给Lua带来更好的性能。请访问。
http://luajit.luaforge.net/来了解这个项目。
与Python等脚本不同,Lua并没有提供强大的库,这是由其定位决定的。所以Lua不适合作为开发独立应用的语言。不过Lua还是有数学运算,字符串处理等基本功能。
Lua的最新版本是5.1。
Lua只有一种数据类型,table。它实际上是一个散列表。用这个来模拟数组,链表等等。从语法上来说,Lua支持以下形式:
Data={} -定义一个表
data.i=1
data.name=jason
data.package={1,2,2,3,56,7}
data.others={}
data.others.a=1
data.others.b=1.1
这就使得Lua有了类似于C的struct的形式,非常方便设计C函数的参数,可以用一个表来传入非常复杂的参数。
2.数据交换简介
1.
Lua和c程序通过一个栈交换数据:struct lua_State。
2.
栈的序号可以从栈顶和栈底开始数,栈底为1,向顶部递增。从栈顶开始计数,栈顶为-1,向栈底递减。通常,它从堆栈顶部开始计数。栈的默认大小是20,可以通过lua_checkstack修改。栈中元素的个数可以通过lua_gettop获得。并不是说栈顶有塑造元素。相反,计算堆栈中顶部元素的正索引,它相当于元素的数量。
3.
Lua调用C函数使用的堆栈是临时的,调用结束后会被销毁。
4.
如何从栈中获取Lua脚本的参数
1.
如果知道Lua脚本中全局变量的名称,可以使用void Lua _ get global (Lua _ state * l,constchar * name)。这个函数将把名字引用的Lua变量的值放在栈顶。
2.
如果想在C函数中获取Lua调用函数所使用的参数:
1.
首先,用lua_gettop检查参数的数量。
2.
使用lua_is.类函数来检测参数的类型并处理错误。
3.
使用lua_to.将参数转换为数字或字符串的类函数。(对于Lua,只有这两种简单类型)
Lua_tonumber返回一个双精度值。
Lua_tostring返回char*
4.
使用lua_remove从堆栈中移除元素。
5.
继续获取下一个元素。因为每次都调用lua_remove,所以每次调用lua_tonumber,使用的索引都会固定为-1,也就是栈顶。
6.
如果lua_istable成立,那么栈顶就是一个表。注意,表格是不能拿出来的,只能把表格中的元素一个一个拿出来。
先把元素名推到栈顶:lua_pushstring(L, I );然后可以用lua_gettable调用它,值会放在栈顶。同时弹出刚刚压入的元素名称。用上面的方法,可以把这个值取出来。记住也要lua_remove。如果table的一个元素也是一个表,重复它。当表的所有元素都被取出后,记住表本身还在堆栈中,用lua_remove删除它。
7.
如果想得到一个数组(所谓数组,其实键是一个从1开始的数值序列的表,值类型是一样的),可以用lua_next遍历这个数组:
首先输入一个空值,然后
while (lua_next(L,-2)!=0)
{
If(lua_isnumber(L,-1)) //确定元素类型,也可能是字符串
{
arrf.add((float)lua_tonumber(L,-1));//获取元素的值
lua_remove(L,-1);
}
}
lua_remove(L,-1);//删除零
5.
如何从C返回数据到Lua脚本
使用lua_push.类函数将数据推入堆栈,并使用return n;告诉Lua返回了几个返回值。Lua天生支持多个返回值,比如x,y=Test()。Lua会根据n从栈中取出相应的数据。
要返回表格:
Lua _ new table(L);//创建一个表并将其放在堆栈的顶部
lua_pushstring(L, my data );//按下键
lua_pushnumber(L,66);//按下数值
lua_settable(L,-3);//弹出键、值,并设置到表中。
lua_pushstring(L, subdata );//按下键
Lua _ new table(L);//按数值,也是表格
lua_pushstring(L, my data );//按下子表的键
lua_pushnumber(L,53);//值
lua_settable(L,-3);//弹出key,value,设置为subtable
lua_settable(L,-3);//此时父表的位置仍然是-3,会弹出key,value(子表)并设置到表中。
lua_pushstring(L, my data 2 );//同上
lua_pushnumber(L,77);
lua_settable(L,-3);
返回1;//现在栈中只有一个表。其他的都被驳回了。
如果要返回一个数组,用下面的代码:(注意关于trick的评论,我在等官方解释。经过验证,只有当windows版本调用dll中的方法时,才会出现此问题。畏缩是正常的)
lua_pushstring(L, arri );
Lua _ new table(L);
{
//一招:否则lua引擎会崩溃。这个元素在Lua脚本中是不可见的
lua_pushnumber(L,-1);
lua_rawseti(L,-2,0);
for(int I=0;I arri . size();我)
{
lua_pushnumber(L,arri);
lua_rawseti(L,-2,I 1);
}
}
lua_settable(L,-3);
可以在Lua中遍历得到的数组,如下所示:
对于I,v在ipairs(data.arri) do
印刷(五)
目标
也许
对于i=1,table.getn(data.arri) do
打印(data.arri)
目标
只有数组可以这样做,name name,value组成的记录不能,table.getn只对数组有效。
6.
由于上述代码的高度相似性,很容易自动生成这些代码。例如,根据C的结构定义:
typedef枚举
{
BR_9600,
BR_4800,
}波德拉特;
typedef结构标志
{
int onoff
int j;
长l;
双d;
char * name
波特率;
}旗帜;
可以自动生成以下代码:
bool DataToLua(标志数据,lua_State *L)
{
Lua _ new table(L);
lua_pushstring(L, onoff );
lua_pushnumber(L,(double)data . onoff);
lua_settable(L,-3);
lua_pushstring(L, j );
lua_pushnumber(L,(double)data . j);
lua_settable(L,-3);
lua_pushstring(L, L );
lua_pushnumber(L,(double)data . L);
lua_settable(L,-3);
lua_pushstring(L, d );
lua_pushnumber(L,(double)data . d);
lua_settable(L,-3);
lua_pushstring(L, name );
lua_pushstring(L,data . name . c _ str());
lua_settable(L,-3);
lua_pushstring(L, rate );
lua_pushnumber(L,(double)(int)data . rate);
lua_settable(L,-3);
返回true
}
LuaToData也类似。
如果把flag用面向对象的方式封装,把DataToLua变成flag类的方法会更方便。
3.C和Lua脚本相互调用的例子
首先,C的主程序初始化Lua脚本引擎,并在脚本中注册一些调用的函数:
Lua要调用的函数
//向脚本返回一个整数数组
静态int l_getarr (lua_State *L)
{
Lua _ new table(L);//创建表格
lua_pushnumber(L,1);//推送值
lua_rawseti(L,-2,1);//设置t[1]=v
lua_pushnumber(L,2);
lua_rawseti(L,-2,2);
lua_pushnumber(L,3);
lua_rawseti(L,-2,3);
lua_pushnumber(L,4);
lua_rawseti(L,-2,4);
返回1;
}
int main()
{
Lua _ State * L=Lua _ open();/*打开Lua */
Lua open _ base(L);/*打开基本库*/
Lua open _ table(L);/*打开表格库*/
Lua open _ string(L);/*打开字符串库。*/
Lua open _ math(L);/*打开数学库。*/
Lua _ pushcffunction(L,L _ getarr);//注册一个函数
lua_setglobal(L, getarr );
if (lua_dofile(L,测试lua。Lua )//加载脚本文件并运行
{
printf(运行脚本失败\ n’);
}
其他
{
lua_getglobal(L, result );//获取左上臂脚本中的全局变量
if(lua_isnumber(L,-1))
{
printf( Lua脚本的结果是%d\n ,lua_tonumber(L,-1));
}
}
Lua _ close(L);
返回0;
}
脚本的代码如下:
array=getarr()
如果数组~=零,那么
结果=1
对于i=1,table.getn(array),1 do
打印(数组)
目标
其他
结果=0
目标
4.参考资料
1.
http://www.lua.org
分享到:
上一篇:LuaBind -最强大的Lua C绑定下一篇:STL映射与推进无序_映射的不同
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。