Lua基本語法-lua與C#的交互(相當簡單詳細的例子)


lua腳本 與 C#的交互


本文提供全流程,中文翻譯。

Chinar堅持將簡單的生活方式,帶給世人!

(擁有更好的閱讀體驗 —— 高分辨率用戶請根據需求調整網頁縮放比例)




1

Lua And C# —— Lua 和 C#的交互准備工作


早期 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文件目錄中

這里寫圖片描述


2

C# Create Lua —— 用C#在lua環境中編寫lua


用簡單的控制台程序 測試,輸出

舉個栗子黑白88

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

3

lua.DoString —— 在C#腳本中編寫Lua腳本


lua.DoString() 用於創建代碼段

舉個栗子黑白88

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

4

lua.DoFile —— 用C#加載Lua腳本文件


lua.DoFile() 用於找到目錄中的Lua文件,並加載

需要將寫好的Lua文件拖到項目中,並且修改屬性為 :如果較新則復制 / 始終復制

否則會出現找不到文件的 報錯信息

不會的請看下圖

這里寫圖片描述

舉個栗子黑白88

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

5

lua.RegisterFunction —— 將C#中的函數/方法 寫入到Lua腳本中


lua.RegisterFunction() 用於將C#中的函數/方法 寫入到Lua腳本中

注冊方法
lua.RegisterFunction (注冊到Lua中以后方法的名稱,程序對象,程序的類型program.GetType().(傳入C#中的方法名:需要是公有方法))

注冊靜態方法
lua.RegisterFunction (注冊到Lua中以后方法的名稱,空,程序的類型 typeof(Program).(傳入C#中的方法名:需要是公有方法))

注冊的方法必須是 public ,否則會找不到

舉個栗子黑白88

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("這個一個靜態空方法");
        }
    }
}

輸出結果:

這是一個空方法
這個一個靜態空方法

6

require —— Lua中引用C#中的類


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 的屬性后,一定要保存,不然還會報錯找不到文件

舉個栗子黑白88

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

7

All —— 全腳本數據


整個腳本項目

1個C#腳本 2個Lua腳本

舉個栗子黑白88

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

8

Error —— 常見報錯點


報錯點1:
require “luanet” :如果DeBug中有luanet.dll文件,則不需要在Lua腳本中再次引用

否則會報錯:
“LuaInterface.LuaException”類型的未經處理的異常在 LuaInterface.dll 中發生,其他信息: error loading module ‘luanet’ from file ‘.\luanet.dll’


報錯點2:
另外,修改 ChinarClass.lua 的屬性后,一定要保存,不然還會報錯找不到文件


報錯點3:
注冊的方法必須是 public ,否則會找不到


報錯點4:
需要將寫好的Lua文件拖到項目中,並且修改屬性為 :如果較新則復制 / 始終復制

否則會出現找不到文件的 報錯信息


報錯點5:
找到項目中的目錄,並將下載好的 lua51.dll luanet.dll 兩個文件,拷貝到DeBug文件目錄中

這一步,在第一步就做好,一步到位!





Chinar

Chinar的GitHub工程案例

直接Down下來運行即可


END

本博客為非營利性個人原創,除部分有明確署名的作品外,所刊登的所有作品的著作權均為本人所擁有,本人保留所有法定權利。違者必究

對於需要復制、轉載、鏈接和傳播博客文章或內容的,請及時和本博主進行聯系,留言,Email: ichinar@icloud.com

對於經本博主明確授權和許可使用文章及內容的,使用時請注明文章或內容出處並注明網址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM