為了搞懂LUA在我們的GDEX中到底怎麼用,我決定研究一下如何比較好的在WPF裡封裝一個基於lua的APP framework。
今天先對Lua for C#進行了一次簡單的封裝。
在C#下用過Lua的人都知道,用C#實現一個函數之後和LUA綁定,需要用到Lua類的RegisterFunction方法。
在函數很少的情況下很好用,但是若需要綁定C#裡成百上千個函數,則麻煩了,添加一個函數,至少每次需要修改兩個地方:函數實現,函數綁定(RegisterFunction)。並且如果在lua中綁定的名字和C#中不一樣,則更麻煩,還需要維護一個函數映射。
今天翻了一下google,翻出GameDev.net上一篇老外的文章,叫《Using Lua with C#》,看了一下,它的方法不錯。(改天考慮翻譯這篇文章),不過他的示例代碼實在是太太太冗長了,大部分是生成函數介紹和函數幫助文檔等,直接忽略。把它最核心的東西拿過來,然後自己封裝了一下,用起來感覺不錯。
基本思想是,使用C#的Attribute來標記函數,實現自動綁定。
核心部分代碼如下(LuaFramework.cs):
[c-sharp] using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Reflection;
using LuaInterface;
namespace WPFLuaFramework
{
/// <summary>
/// Lua函數描述特性類
/// </summary>
public class LuaFunction : Attribute
{
private String FunctionName;
public LuaFunction(String strFuncName)
{
FunctionName = strFuncName;
}
public String getFuncName()
{
return FunctionName;
}
}
/// <summary>
/// Lua引擎
/// </summary>
class LuaFramework
{
private Lua pLuaVM = new Lua();//lua虛擬機
/// <summary>
/// 注冊lua函數
/// </summary>
/// <param name="pLuaAPIClass">lua函數類</param>
public void BindLuaApiClass( Object pLuaAPIClass )
{
foreach (MethodInfo mInfo in pLuaAPIClass.GetType().GetMethods())
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
{
string LuaFunctionName = (attr as LuaFunction).getFuncName();
pLuaVM.RegisterFunction(LuaFunctionName, pLuaAPIClass, mInfo);
}
}
}
/// <summary>
/// 執行lua腳本文件
/// </summary>
/// <param name="luaFileName">腳本文件名</param>
public void ExecuteFile(string luaFileName)
{
try
{
pLuaVM.DoFile(luaFileName);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
/// <summary>
/// 執行lua腳本
/// </summary>
/// <param name="luaCommand">lua指令</param>
public void ExecuteString(string luaCommand)
{
try
{
pLuaVM.DoString(luaCommand);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Reflection;
using LuaInterface;
namespace WPFLuaFramework
{
/// <summary>
/// Lua函數描述特性類
/// </summary>
public class LuaFunction : Attribute
{
private String FunctionName;
public LuaFunction(String strFuncName)
{
FunctionName = strFuncName;
}
public String getFuncName()
{
return FunctionName;
}
}
/// <summary>
/// Lua引擎
/// </summary>
class LuaFramework
{
private Lua pLuaVM = new Lua();//lua虛擬機
/// <summary>
/// 注冊lua函數
/// </summary>
/// <param name="pLuaAPIClass">lua函數類</param>
public void BindLuaApiClass( Object pLuaAPIClass )
{
foreach (MethodInfo mInfo in pLuaAPIClass.GetType().GetMethods())
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
{
string LuaFunctionName = (attr as LuaFunction).getFuncName();
pLuaVM.RegisterFunction(LuaFunctionName, pLuaAPIClass, mInfo);
}
}
}
/// <summary>
/// 執行lua腳本文件 www.2cto.com
/// </summary>
/// <param name="luaFileName">腳本文件名</param>
public void ExecuteFile(string luaFileName)
{
try
{
pLuaVM.DoFile(luaFileName);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
/// <summary>
/// 執行lua腳本
/// </summary>
/// <param name="luaCommand">lua指令</param>
public void ExecuteString(string luaCommand)
{
try
{
pLuaVM.DoString(luaCommand);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
}
我的LUA API類如下,用於實現C# for lua的函數(LuaAPI.cs)
[c-sharp] using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace WPFLuaFramework
{
class LuaAPI
{
[LuaFunction("lua1")]
public void a1()
{
MessageBox.Show("a1 called");
}
[LuaFunction("lua2")]
public int a2()
{
MessageBox.Show("a2 called");
return 0;
}
[LuaFunction("lua3")]
public void a3(string s)
{
MessageBox.Show("a3 called");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace WPFLuaFramework
{
class LuaAPI
{
[LuaFunction("lua1")]
public void a1()
{
MessageBox.Show("a1 called");
}
[LuaFunction("lua2")]
public int a2()
{
MessageBox.Show("a2 called");
return 0;
}
[LuaFunction("lua3")]
public void a3(string s)
{
MessageBox.Show("a3 called");
}
}
}
最後看調用代碼,是不是很簡單
[c-sharp] LuaFramework test = new LuaFramework();
test.BindLuaApiClass(new LuaAPI());
test.ExecuteFile("test.lua");
test.ExecuteString("lua1()");
LuaFramework test = new LuaFramework();
test.BindLuaApiClass(new LuaAPI());
test.ExecuteFile("test.lua");
test.ExecuteString("lua1()");
LUA代碼如下
lua1();
lua2();
lua3("test");
摘自 碼農成長日記