lua腳本 與 C#的互動
本文提供全流程,中文翻譯。 Chinar堅持将簡單的生活方式,帶給世人! (擁有更好的閱讀體驗 —— 高分辨率使用者請根據需求調整網頁縮放比例) |
早期 Lua 和 C# 之間的互動,需要用Lua官方做好的接口 LuaInterface.dll 等檔案來實作
檔案的下載下傳直接跳轉Lua官方網站:
LuaInterface完成下載下傳
點選 luainterface 連結 ↓↓
點選 1.5.3 連結 開始下載下傳
下載下傳完成後解壓壓縮檔案,并打開 Built 檔案夾
目錄中的3個檔案: lua51.dll 、 LuaInterface.dll 、 luanet.dll 是暫時需要用到的
打開VS,建立一個控制台腳本
将下載下傳好的 LuaInterface.dll 檔案拖到項目中
并按照步驟添加引用
圖中我沒有 using LuaInterface; 請自己添加上
找到項目中的目錄,并将下載下傳好的 lua51.dll 、 luanet.dll 兩個檔案,拷貝到DeBug檔案目錄中
用簡單的控制台程式 測試,輸出
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
lua["num"] = 66; //用C#腳本在lua環境中,建立一個變量
lua["str"] = "chinar"; //用C#腳本在lua環境中,建立一個字元串變量
Console.WriteLine(lua["num"]); //輸出
Console.WriteLine(lua["str"]); //輸出
Console.ReadKey(); //等待輸入
}
}
}
輸出結果:
66
chinar
lua.DoString() 用于建立代碼段
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
lua.DoString("num=666"); //用C#腳本在lua環境中,建立一段lua腳本:num=666
lua.DoString("str='chianr666'"); //用C#腳本在lua環境中,建立一段lua腳本:str='chianr666'
object[] values = lua.DoString("return num,str"); //用一個object數組 去接受傳回值
foreach (var value in values) //周遊 values 數組中的元素
{
Console.WriteLine(value); //輸出
}
Console.ReadKey(); //等待輸入
}
}
}
666
chianr666
lua.DoFile() 用于找到目錄中的Lua檔案,并加載
需要将寫好的Lua檔案拖到項目中,并且修改屬性為 :如果較新則複制 / 始終複制
否則會出現找不到檔案的 報錯資訊
不會的請看下圖
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
lua.DoFile("Chinar.lua"); //加載lua檔案 —— lua.DoFile(檔案名)
Console.ReadKey(); //等待輸入
}
}
}
下邊是 Chinar.lua 檔案
print('I am Chianr')
MyTable={1,22,333,4444,55555,666666}
print(table.concat(MyTable)..'I am Chianr')
I am Chianr
122333444455555666666I am Chianr
lua.RegisterFunction() 用于将C#中的函數/方法 寫入到Lua腳本中
注冊方法
lua.RegisterFunction (注冊到Lua中以後方法的名稱,程式對象,程式的類型program.GetType().(傳入C#中的方法名:需要是公有方法))
注冊靜态方法
lua.RegisterFunction (注冊到Lua中以後方法的名稱,空,程式的類型 typeof(Program).(傳入C#中的方法名:需要是公有方法))
注冊的方法必須是 public ,否則會找不到
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
Program program = new Program(); //聲明一個對象
//lua.RegisterFunction 注冊方法(注冊到Lua中以後方法的名稱,程式對象,程式的類型program.GetType().(傳入C#中的方法名:需要是公有方法))
lua.RegisterFunction("LuaChinarTest", program, program.GetType().GetMethod("ChinarTest"));
//然後用lua.DoString(Lua中方法名())調用測試
lua.DoString("LuaChinarTest()");
//lua.RegisterFunction 注冊靜态方法(注冊到Lua中以後方法的名稱,空,程式的類型 typeof(Program).(傳入C#中的方法名:需要是公有方法))
lua.RegisterFunction("LuaChinarStaticTest", null, typeof(Program).GetMethod("ChinarStaticTest"));
//然後用lua.DoString(Lua中靜态方法名())調用測試
lua.DoString("LuaChinarStaticTest()");
Console.ReadKey(); //等待輸入
}
/// <summary>
/// 一個測試方法
/// </summary>
public void ChinarTest()
{
Console.WriteLine("這是一個空方法");
}
/// <summary>
/// 一個靜态測試方法
/// </summary>
public static void ChinarStaticTest()
{
Console.WriteLine("這個一個靜态空方法");
}
}
}
這是一個空方法
這個一個靜态空方法
Lua 調用 C# 的類需要: LuaInterface.dll 和 luanet.dll
luanet.dll 拷貝到工程 DeBug 輸出目錄中
lua 腳本中就不需要使用 package.cpath 和 require 了
這點,在第一步 配置引用資訊的時候,就做過了,如果沒有做的報錯了。請傳回第一步
報錯點1:
require “luanet” :如果DeBug中有luanet.dll檔案,則不需要在Lua腳本中再次引用
否則會報錯:
“LuaInterface.LuaException”類型的未經處理的異常在 LuaInterface.dll 中發生,其他資訊: error loading module ‘luanet’ from file ‘.\luanet.dll’
報錯點2:
另外,修改 ChinarClass.lua 的屬性後,一定要儲存,不然還會報錯找不到檔案
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
lua.DoFile("ChinarClass.lua"); //Lua引用C#中的類
Console.ReadKey(); //等待輸入
}
public int ChinarNum = 60; //整形變量
public string Name = "Chinar"; //字元串變量
/// <summary>
/// 用來讓Lua腳本測試的方法
/// </summary>
public void ChinarTestFun()
{
Console.WriteLine("你好,Chinar");
}
/// <summary>
/// Ref方法,參數
/// </summary>
/// <param name="name"></param>
/// <param name="count"></param>
public void TestRef(string name, ref int count)
{
Console.WriteLine(name);
Console.WriteLine(count);
count = name.Length;
}
/// <summary>
/// Out方法,參數
/// </summary>
/// <param name="name"></param>
/// <param name="count"></param>
public void TestOut(string name, out int count)
{
Console.WriteLine(name);
count = name.Length;
}
}
}
ProxyType(System.Int32): 46104728
- - - - - - - - - - - - - - - - - - - - - - - - - -
60
你好,Chinar
chinar.fun
nil 10
chinar.fun
8
nil 10
整個腳本項目
1個C#腳本 2個Lua腳本
using System;
using LuaInterface; //引用命名空間
namespace ChinarTest
{
/// <summary>
/// 測試類
/// </summary>
class Program
{
static void Main(string[] args)
{
Lua lua = new Lua(); //建立一個lua解釋器
lua["num"] = 66; //用C#腳本在lua環境中,建立一個變量
lua["str"] = "chinar"; //用C#腳本在lua環境中,建立一個字元串變量
Console.WriteLine(lua["num"]); //輸出
Console.WriteLine(lua["str"]); //輸出
lua.DoString("num=666"); //用C#腳本在lua環境中,建立一段lua腳本:num=666
lua.DoString("str='chianr666'"); //用C#腳本在lua環境中,建立一段lua腳本:str='chianr666'
object[] values = lua.DoString("return num,str"); //用一個object數組 去接受傳回值
foreach (var value in values) //周遊 values 數組中的元素
{
Console.WriteLine(value); //輸出
}
lua.DoFile("Chinar.lua"); //加載lua檔案 —— lua.DoFile(檔案名)
Program program = new Program(); //聲明一個對象
//lua.RegisterFunction 注冊方法(注冊到Lua中以後方法的名稱,程式對象,程式的類型program.GetType().(傳入C#中的方法名:需要是公有方法))
lua.RegisterFunction("LuaChinarTest", program, program.GetType().GetMethod("ChinarTest"));
//然後用lua.DoString(Lua中方法名())調用測試
lua.DoString("LuaChinarTest()");
//lua.RegisterFunction 注冊靜态方法(注冊到Lua中以後方法的名稱,空,程式的類型 typeof(Program).(傳入C#中的方法名:需要是公有方法))
lua.RegisterFunction("LuaChinarStaticTest", null, typeof(Program).GetMethod("ChinarStaticTest"));
//然後用lua.DoString(Lua中靜态方法名())調用測試
lua.DoString("LuaChinarStaticTest()");
lua.DoFile("ChinarClass.lua"); //Lua引用C#中的類
Console.ReadKey(); //等待輸入
}
/// <summary>
/// 一個測試方法
/// </summary>
public void ChinarTest()
{
Console.WriteLine("這是一個空方法");
}
/// <summary>
/// 一個靜态測試方法
/// </summary>
public static void ChinarStaticTest()
{
Console.WriteLine("這個一個靜态空方法");
}
public int ChinarNum = 60; //整形變量
public string Name = "Chinar"; //字元串變量
/// <summary>
/// 用來讓Lua腳本測試的方法
/// </summary>
public void ChinarTestFun()
{
Console.WriteLine("你好,Chinar");
}
/// <summary>
/// Ref方法,參數
/// </summary>
/// <param name="name"></param>
/// <param name="count"></param>
public void TestRef(string name, ref int count)
{
Console.WriteLine(name);
Console.WriteLine(count);
count = name.Length;
}
/// <summary>
/// Out方法,參數
/// </summary>
/// <param name="name"></param>
/// <param name="count"></param>
public void TestOut(string name, out int count)
{
Console.WriteLine(name);
count = name.Length;
}
}
}
Chinar.lua 檔案
print('I am Chianr')
MyTable={1,22,333,4444,55555,666666}
print(table.concat(MyTable)..'I am Chianr')
ChinarClass.lua 檔案
-- 如果DeBug中有luanet.dll檔案,則不需要再次引用
-- require "luanet"
-- 加載CLR類型("命名空間")
luanet.load_assembly("System")
-- 加載命名空間下的類
Int32 = luanet.import_type("System.Int32")
-- 輸出
print(Int32)
print('- - - - - - - - - - - - - - - - - - - - - - - - - - ')
-- 加載CLR類型("命名空間"ChinarTest)
luanet.load_assembly("ChinarTest")
-- 加載命名空間下的類Program
Pro=luanet.import_type("ChinarTest.Program")
-- 執行個體化一個類對象
pro=Pro()
-- 輸出
print(pro.ChinarNum)
-- 調用C#中的方法
pro:ChinarTestFun()
-- 調用Out方法,out參數不需要傳入值,會直接傳回類型為一個:表
-- 由于C#那邊是一個空傳回值的方法,是以第一個傳回為空
-- 第二個傳回 out參數
void,stringCount=pro:TestOut("chinar.fun")
print(void,stringCount)
-- Ref參數
void1,stringCount1=pro:TestRef("chinar.fun",8)
print(void1,stringCount1)
66
chinar
666
chianr666
I am Chianr
122333444455555666666I am Chianr
這是一個空方法
這個一個靜态空方法
ProxyType(System.Int32): 12289376
- - - - - - - - - - - - - - - - - - - - - - - - - -
60
你好,Chinar
chinar.fun
nil 10
chinar.fun
8
nil 10
另外,修改 ChinarClass.lua 的屬性後,一定要儲存,不然還會報錯找不到檔案
報錯點3:
注冊的方法必須是 public ,否則會找不到
報錯點4:
否則會出現找不到檔案的 報錯資訊
報錯點5:
這一步,在第一步就做好,一步到位!
Chinar
Chinar的GitHub工程案例直接Down下來運作即可
END
本部落格為非營利性個人原創,除部分有明确署名的作品外,所刊登的所有作品的著作權均為本人所擁有,本人保留所有法定權利。違者必究
對于需要複制、轉載、連結和傳播部落格文章或内容的,請及時和本部落客進行聯系,留言,Email: [email protected]
對于經本部落客明确授權和許可使用文章及内容的,使用時請注明文章或内容出處并注明網址