参考链接:
https://www.jianshu.com/p/7cc9ca7efe18
http://www.360doc.com/content/16/0830/21/7014874_587111940.shtml#
零.原理
lua与其他语言的交互,都是基于栈的结构来交互的。栈的元素为lua中的值(table,string,nil等8种基本类型)
如果用正数索引来表示,则栈底为1,索引往上递增;如果用负数索引来表示,则栈顶为-1,索引往下递减
lua与其他语言的交互过程如下:
一.c#调用lua
1 using LuaInterface;
2 using System;
3
4 namespace TestLua
5 {
6 class Program
7 {
8 static IntPtr L;
9
10 static void Main(string[] args)
11 {
12 int sum;
13 L = LuaDLL.luaL_newstate();//创建lua状态机
14 LuaDLL.luaL_openlibs(L);//打开Lua状态机中所有Lua标准库
15 LuaDLL.luaL_dofile(L, "add.lua");//加载lua脚本
16 sum = LuaAdd(8, 9);
17 Console.WriteLine(sum);
18 LuaDLL.lua_close(L);//关闭lua状态机
19 Console.ReadKey();
20 }
21
22 static int LuaAdd(int x, int y)
23 {
24 int sum = -1;
25 LuaDLL.lua_getglobal(L, "AddFunc");//函数名
26 LuaDLL.lua_pushnumber(L, x);//参数入栈
27 LuaDLL.lua_pushnumber(L, y);//参数入栈
28 LuaDLL.lua_call(L, 2, 1);//开始调用函数,有2个参数,1个返回值
29 sum = (int)LuaDLL.lua_tonumber(L, -1);//取出返回值
30 LuaDLL.lua_pop(L, 1);
31 return sum;
32 }
33 }
34 }
add.lua
1 function AddFunc(x,y)
2 return x + y
3 end
输出:
分析:
lua_getglobal(L, "AddFunc"),将lua中的全局变量AddFunc进栈
lua_pushnumber(L, x),将参数x进栈,当2个参数都进栈后,栈是这样的(从栈底到栈顶):AddFunc->8->9
lua_call(L, 2, 1),调用后,栈的元素都出栈,然后返回值进栈,栈是这样的(从栈底到栈顶):17
lua_tonumber(L, -1),将栈顶元素转换为number用于赋值
lua_pop(L, 1),栈顶元素出栈,此时栈为空
二.lua调用c#
1 using LuaInterface;
2 using System;
3
4 namespace TestLua
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 IntPtr L = LuaDLL.luaL_newstate();//创建lua状态机
11 LuaDLL.luaL_openlibs(L);//打开Lua状态机中所有Lua标准库
12 LuaDLL.lua_pushstdcallcfunction(L, SayHello);
13 LuaDLL.lua_setglobal(L, "AAA");
14 LuaDLL.luaL_dostring(L, "print(AAA(\"123\"))");
15 LuaDLL.lua_close(L);//关闭lua状态机
16 Console.ReadKey();
17 }
18
19 static int SayHello(IntPtr L)
20 {
21 string s = LuaDLL.lua_tostring(L, 1);
22 LuaDLL.lua_pushstring(L, "Hello " + s);
23 return 1;
24 }
25 }
26 }
输出:
分析:
lua_pushstdcallcfunction(L, SayHello),将c#的方法SayHello进栈
lua_setglobal(L, "AAA"),将栈顶元素设置成lua中的全局变量AAA,此时栈顶是function类型,即AAA=function () end
luaL_dostring(L, "print(AAA(\"123\"))"),在lua中将参数123进栈
lua_tostring(L, 1),在c#中将栈顶元素123转换为string用于操作,栈是这样的(从栈底到栈顶):123
lua_pushstring(L, "Hello " + s),在c#中将返回值进栈,供lua使用,栈是这样的(从栈底到栈顶):123->Hello 123
注意:
1.lua调用c#,涉及到将c#方法的注册到lua中,对应上面的语句lua_pushstdcallcfunction和lua_setglobal,其中lua_pushstdcallcfunction的原型为:
public static void lua_pushstdcallcfunction(IntPtr luaState, LuaCSFunction function);
而LuaCSFunction的原型为:
public delegate int LuaCSFunction(IntPtr luaState);
即要注册的方法返回值必须为int(表示返回值的个数),参数必须为IntPtr(指针,指向lua状态机)
2.每个注册的方法(如上面的SayHello)都有1个私有栈,并且第1个参数就在栈的1位置,第2个参数就在栈的2位置,以此类推
所以上面的LuaDLL.lua_tostring(L, 1)拿到的是第1个参数
3.如果注册的方法有返回值,则按照返回顺序依次入栈,最后一个返回值在栈的-1位置
三.unity相关
1.wrap文件
经过上面lua调用c#的介绍,再来看生成的wrap文件,会发现很熟悉(下面以UnityEngine_GameObjectWrap为例):