Unity3D开发小贴士(五)Lua调用C#

Unity3D开发小贴士(三)愉快的使用Lua开发介绍了如何将ToLua插件添加到Unity项目中,Unity3D开发小贴士(四)调用Lua脚本讲解了如何在C#中调用Lua脚本。
本文就介绍一下如何在Lua中调用C#。

首先我们先写一个C#类:

using UnityEngine;
using System.Collections;

public class CSharpFunc {
	public void TestCSharpFunc()
	{
		Debug.Log ("Hello lua in C#");
	}
}

然后在Unity编辑器中点击Lua->Gen LuaWrap + Binder,等待生成完毕。

在场景中添加一个GameObject,挂上LuaClient脚本。

然后在Main.Lua中添加:

local csharpFunc = CSharpFunc.New()
csharpFunc:TestCSharpFunc()

点击运行,便会打印:

Hello Lua in C#

然后我们在为CSharpFunc添加一个TestCSharpFunc的重载版本:

	public void TestCSharpFunc(string str)
	{
		Debug.Log ("Hello lua in C#" + str);
	}
再次点击Gen LuaWrap + Binder。

在Main.Lua中添加:

csharpFunc:TestCSharpFunc("[Lua]")

点击运行,便会多打印一行:

Hello Lua in C#[Lua]


知道如何运用之后,我们看一下ToLua都为我们做了些什么。

Assets/Source/Generate/LuaBinder.cs文件中

L.BeginModule(null);

L.BeginModule("UnityEngine");

之间多了一行:

CSharpFuncWrap.Register(L);


另外同一级目录下面多了一个CSharpFuncWrap.cs文件。

文件内容:

//this source code was auto-generated by tolua#, do not modify it
using System;
using LuaInterface;

public class CSharpFuncWrap
{
	public static void Register(LuaState L)
	{
		L.BeginClass(typeof(CSharpFunc), typeof(System.Object));
		L.RegFunction("TestCSharpFunc", TestCSharpFunc);
		L.RegFunction("New", _CreateCSharpFunc);
		L.RegFunction("__tostring", ToLua.op_ToString);
		L.EndClass();
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int _CreateCSharpFunc(IntPtr L)
	{
		try
		{
			int count = LuaDLL.lua_gettop(L);

			if (count == 0)
			{
				CSharpFunc obj = new CSharpFunc();
				ToLua.PushObject(L, obj);
				return 1;
			}
			else
			{
				return LuaDLL.luaL_throw(L, "invalid arguments to ctor method: CSharpFunc.New");
			}
		}
		catch(Exception e)
		{
			return LuaDLL.toluaL_exception(L, e);
		}
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int TestCSharpFunc(IntPtr L)
	{
		try
		{
			int count = LuaDLL.lua_gettop(L);

			if (count == 1 && TypeChecker.CheckTypes(L, 1, typeof(CSharpFunc)))
			{
				CSharpFunc obj = (CSharpFunc)ToLua.ToObject(L, 1);
				obj.TestCSharpFunc();
				return 0;
			}
			else if (count == 2 && TypeChecker.CheckTypes(L, 1, typeof(CSharpFunc), typeof(string)))
			{
				CSharpFunc obj = (CSharpFunc)ToLua.ToObject(L, 1);
				string arg0 = ToLua.ToString(L, 2);
				obj.TestCSharpFunc(arg0);
				return 0;
			}
			else
			{
				return LuaDLL.luaL_throw(L, "invalid arguments to method: CSharpFunc.TestCSharpFunc");
			}
		}
		catch(Exception e)
		{
			return LuaDLL.toluaL_exception(L, e);
		}
	}
}

L.BeginClass将该类型(CSharpFunc)和其父类(System.Object)注册到Lua,分别注册了TestCSharpFunc和New以及__tostring函数,最后EndClass结束注册。

__tostring注册了ToLua的静态方法,这里就不赘述了。

New函数里首先获取栈的深度,如果数量为0(没有参数),便创建CSharpFunc对象,并把它压入栈中。否则(栈深度大于零,即为New函数传入了参数),便扔出异常。

TestCSharpFunc函数与New函数类似,只不过因为有两个重载版本,所以对栈深度做了两个分歧。


当然,我们还可以添加带返回值的C#方法。

例如一个简单的判定:

	public bool IsPositive(int num)
	{
		return num > 0;
	}

点击Gen LuaWrap + Binder


Main.lua里添加:

print(csharpFunc:IsPositive(-10))

毫无意外的会多打印一个false。


CSharpFuncWrap.cs文件的Register方法中,在BeginClass和EndClass之间多了一行:

		L.RegFunction("IsPositive", IsPositive);

并且多了一个方法:

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int IsPositive(IntPtr L)
	{
		try
		{
			ToLua.CheckArgsCount(L, 2);
			CSharpFunc obj = (CSharpFunc)ToLua.CheckObject(L, 1, typeof(CSharpFunc));
			int arg0 = (int)LuaDLL.luaL_checknumber(L, 2);
			bool o = obj.IsPositive(arg0);
			LuaDLL.lua_pushboolean(L, o);
			return 1;
		}
		catch(Exception e)
		{
			return LuaDLL.toluaL_exception(L, e);
		}
	}

虽然写法变了一下,但是逻辑跟之前的那些函数并没有什么区别,只不过在本方法返回之前,将 IsPositive的结果o压入Lua栈中。

你可能感兴趣的:(Unity3D,Unity3D开发小贴士)