参考链接:
https://www.cnblogs.com/lijiajia/p/8284328.html
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为例):