用C#調用Lua腳本


一、引言

         學習Redis也有一段時間了,感觸還是頗多的,但是自己很清楚,路還很長,還要繼續。上一篇文章簡要的介紹了如何在Linux環境下安裝Lua,並介紹了在Linux環境下如何編寫Lua腳本和運行。由於我們這個系列是以Redis為主,所以也介紹了Redis和Lua如何進行整合、運行。

        在Lua腳本中有一個很重要的數據類型,那就是table類型,大家可以把Lua的table類型暫時理解為數組,只是Lua的table類型的下標可以是數字,可以是字符,除了(nil)類型,其他類型都可以做為table類型的下標。我們在使用Redis和Lua的過程中,比較多的會用到這個table類型,今天的主要任務就是介紹table類型的使用、CJSON的解析和如何通過C#語言來對Redis和Lua的進行整合操作。后續我還會推出針對Lua腳本語法的文章來擴充這個系列。

二、Lua簡介
    
         Lua 是一個小巧的腳本語言。其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。Lua由標准C編寫而成,幾乎在所有操作系統和平台上都可以編譯,運行。Lua並沒有提供強大的庫,這是由它的定位決定的。所以Lua不適合作為開發獨立應用程序的語言。

        在Redis中使用Lua有很多好處,它可以減少網絡開銷,把多個操作一次性打包執行。Lua腳本天生支持原子性的操作,避免開啟第三方事務,提高了性能。代碼重用也是一個重要的好處,寫好的代碼會被加載到Redis內存中,可以供其他客戶端使用,減少重復勞動。Lua腳本使用C語言寫成的,執行速度很快,並天然具有可移植性,也是代碼重用的很好體現。一個完整的Lua解釋器,不過200k,在目前所有腳本引擎中,Lua的速度是最快的。這一切都決定了Lua是作為嵌入式腳本的最佳選擇。

三、基本操作

    1、在Linux環境下安裝CJSON和簡單使用

        cjson是一個類型轉換工具類,可以把一個字符串轉換為Lua的類型,如果類型嵌套多層,還可以轉換為Lua的table類型,所以這個工具很重要,在編寫Lua腳本的過程中經常使用,所以我們先來介紹cjson這個工具類的安裝和使用。

        1.1、下載CJSON軟件包,官網地址:https://www.kyne.com.au/~mark/software/lua-cjson.php。

             [root@linux cjson]# pwd
             /root/software/download/cjson

             [root@linux cjson]# wget https://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.tar.gz

              
                       

        1.2、解壓到當前目錄,當然也可以解壓到其他目錄,解壓到其他目錄,比如:/usr/local,命令如下:tar zxvf lua-cjson-2.1.0.tar.gz -C(大寫的) /usr/local

復制代碼
             //當前目錄
             [root@linux cjson]# pwd
             /root/software/download/cjson

             //顯示當前目錄下的文件和目錄
             [root@linux cjson]# ls
             lua-cjson-2.1.0.tar.gz

             //解壓到當前目錄
             [root@linux cjson]# tar zxvf lua-cjson-2.1.0.tar.gz [-C /usr/local]
             //...
             complete!
復制代碼


                     

                     解壓成功后的目錄結構:


                      

         1.3、進入到解壓目錄的根目錄,准備修改Makefile文件,用vim打開的修改文件的時候,注意名稱大小寫拼寫正確。

復制代碼
              //當前目錄
              [root@linux cjson]# pwd
              /root/software/download/cjson

              //進入到CJSON的解壓根目錄
              [root@linux cjson]# cd lua-cjson-2.1.0
             
              //進入到根目錄,修改Makefile文件
              [root@linux lua-cjson-2.1.0]# vim Makefile
復制代碼

              
                        

         1,4、vim 進入Makefile文件,修改PREFIX選項,修改完畢,按ESC按鈕,再按:,最后按wq,保存退出。

             //當前目錄
             [root@linux lua-cjson-2.1.0]# pwd
             /root/software/download/cjson/lua-cjson-2.1.0

                     
                        

         1.5、使用make命令在解壓文件的根目錄下進行編譯。

復制代碼
             //當前目錄
             [root@linux lua-cjson-2.1.0]# pwd
             /root/software/download/cjson/lua-cjson-2.1.0

             [root@linux lua-cjson-2.1.0]# make
             //開始編譯
復制代碼

 

                        

         1.6、最后使用 make install 安裝cjson軟件包。

復制代碼
             //當前目錄
             [root@linux lua-cjson-2.1.0]# pwd
             /root/software/download/cjson/lua-cjson-2.1.0

             [root@linux lua-cjson-2.1.0]# make install
             //開始安裝
復制代碼

                      

         1.7、cjson.so文件很重要,是核心運行文件,如果出現錯誤,在某某目錄沒有找到cjson這個文件,就在其他目錄找到,並拷貝到目標目錄,可以解決所出現的錯誤。

              [root@linux program]# pwd
              /root/application/program

              //拷貝sjson.so文件到指定目錄
              [root@linux program]# sudo cp -r cjson/lib/lua/5.1/cjson.so  /usr/local/lib/lua/5.3


                     錯誤如圖:

                       

                         只需要把cjson.so文件拷貝到【/usr/local/lib/lua/5.3(這個版本具體情況要看具體情況)/】目錄下就可以了

            1.8、安裝完成,開始測試cjson安裝是否成功,此步驟有兩步,必須全部都完成。

復制代碼
             //1、從Linux命令行模式進入lua命令行測試安裝是否正確
             [root@linux lua-cjson-2.1.0]# lua
             Lua 5.3.4 Copyright (C) 1994-2017 Lua.org PUC-Rio
             >local cjson=require("cjson")
             >local cjson2=require "cjson.safe"
             //以上所有操作沒有提示任何錯誤

             //2、我們在Linux命令行下在執行lua命令,執行lua腳本,測試是否安裝成功

             //05.lua腳本文件的源碼
             local cjson=require "cjson"
             local smapleJson=[[{"age":"23","testArray":{"array":[8,9,1,14,15]},"baidu":"www.baidu.com"}]];
             local data=cjson.decode(sampleJson)
             print(data["age"]);
             print(data["testArray"]["array"][1])
             //沒有提示任何錯誤,安裝成功

//在Linux環境下執行剛才的Lua腳本 [root@linux lua-cjson-2.1.0]# lua /root/application/program/luascript/05.lua 23 8.0 //安裝成功
復制代碼

 

                        
 

    2、在Linux環境下,在Lua腳本里面使用cjson來解析類型。

復制代碼
 1           //cjsonDemo.lua的源代碼如下:
 2 
 3           local cjson = require "cjson"
 4           local retTable = {};    --最終產生json的表
 5 
 6           --順序數值
 7 
 8           local intDatas = {};
 9           intDatas[1] = 100;
10           intDatas[2] = "100";
11 
12           --數組
13 
14           local aryDatas = {};
15           aryDatas[1] = {};
16           aryDatas[1]["鍵11"] = "值11";
17           aryDatas[1]["鍵12"] = "值12";
18           aryDatas[2] = {};
19           aryDatas[2]["鍵21"] = "值21";
20           aryDatas[2]["鍵22"] = "值22";
21 
22           --對Table賦值
23 
24           retTable["鍵1"] = "值1";
25           retTable[2] = 123;
26           retTable["int_datas"] = intDatas;
27           retTable["aryDatas"] = aryDatas;
28  
29           --將表數據編碼成json字符串
30 
31           local jsonStr = cjson.encode(retTable);
32           print(jsonStr);
33 
34           return retTable;
35 
36           //以上為Lua源碼
復制代碼

 

復制代碼
          //開始執行命令
          [root@linux luascript]# pwd
          /root/application/program/luascript  //lua腳本存放的位置

          [root@linux luascript]# lua cjsonDemo.lua
          {"int_datas":[100,"100"],"2":123,"鍵1":"值1","aryDatas":[{"鍵12":"值12","鍵11":"值11"},{"鍵21":"值21","鍵22":"值22"}]}
復制代碼


          執行效果如圖:
          
                  

    3、在Windows環境下,用C#執行lua腳本

            3.1、在VS2015中建一個C#控制台應用程序,並添加LuaInterface.dll的引用

                       LuaInterface下載地址:http://luaforge.net/projects/luainterface/ (下載luainterface-1.5.3,這里面的資源比較多)

                 LuaInterface.Lua類是CLR訪問Lua解釋器的主要接口,一個LuaInterface.Lua類對象就代表了一個Lua解釋器(或Lua執行環境),Lua解釋器可以同時存在多個,並且它們之間是完全相互獨立的。
                    

           3.2、在Windows環境下,Lua腳本文件使用上面提到的源文件 cjsonDemo.lua。

                        文件所在地址如下:C:\Users\Administrator\Desktop\Redis\LuaScript\cjsonDemo.lua

復制代碼
                //源碼如下:

                local retTable = {};    --最終產生json的表

                --順序數值
                local intDatas = {};
                intDatas[1] = 100;
                intDatas[2] = "100";

                --數組
                local aryDatas = {};
                aryDatas[1] = {};
                aryDatas[1]["鍵11"] = "值11";
                aryDatas[1]["鍵12"] = "值12";
                aryDatas[2] = {};
                aryDatas[2]["鍵21"] = "值21";
                aryDatas[2]["鍵22"] = "值22";

                --對Table賦值
                retTable["鍵1"] = "值1";
                retTable[2] = 123;
                retTable["int_datas"] = intDatas;
                retTable["aryDatas"] = aryDatas;

                return retTable;
復制代碼


         3.3、測試代碼如下:

復制代碼
           using LuaInterface;  // 引入的dll
           using System;
           using System.Collections.Generic;
           using System.Linq;
           using System.Text;
           using System.Threading.Tasks;

           namespace CSharpPinvokeLuaDemo
           {
               class Program
               {
                   static void Main(string[] args)
                   {
                        // 新建一個Lua解釋器,每一個Lua實例都相互獨立, 一個global全局域
                        Lua lua = new Lua();
                        //---------------------------------------------------
                        // Lua的索引操作[]可以創建、訪問、修改global域
                        lua["age"] = 20;
                        lua["name"] = "Mr.huang";

                        string luaCode = "print(\"This is Lua code\")";
                        lua.DoString(luaCode);//執行lua腳本代碼
                        object[] result=lua.DoFile(@"C:\Users\Administrator\Desktop\Redis\LuaScript\cjsonDemo.lua");//執行lua腳本文件,這里我直接用了絕對定位

                        double age = (double)lua["age"];

                        Console.WriteLine("age = {0}", age);
                        Console.WriteLine("width = {0}", lua["width"]);
                        Console.ReadKey();
                   }
              }
         }
復制代碼


         3.4、有可能拋出的異常:FileLoadException,異常內容:其他信息: 混合模式程序集是針對“v2.0.50727”版的運行時生成的,在沒有配置其他信息的情況下,無法在 4.0 運行時中加載該程序集。

                 該問題解決不是很難,只要在配置文件里增加一點配置就能解決。配置代碼如下:

                <startup useLegacyV2RuntimeActivationPolicy="true">
                    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
                    <supportedRuntime version="v2.0.50727"/>
                </startup>


              在原來.NET2.0,.NET3.5的時候,由於程序運行環境本質還是.NET2.0,而到了.NET4.0由於整個程序集的版本更新,以前使用.NET2.0所編寫的程序集與.NET4.0的程序集繼續互操作的時候就會出現上面所說的兼容性問題。通過MSDN,我們可以知道,startup配置節中的useLegacyV2RuntimeActivationPolicy屬性是在.NET4.0中新增的,默認是false,表示:使用默認的 .NET Framework 4 激活策略,該激活策略將加載 .NET Framework 4 通過使用公共語言運行時 (CLR) 版本 4 所創建的程序集,以及 CLR 早期版本通過使用受支持的低於版本 4 的最高 CLR 版本所創建的程序集。

             現在如果當程序在.NET4.0環境下要使用.NET2.0及.NET3.5的程序時就必須將useLegacyV2RuntimeActivationPolicy設置為true,同時還要注意,需要在startup配置節的字節中添加supportedRuntime配置節,並指定為“v4.0”,表示使用.NET4.0運行時來運行程序。


四、結束

       今天就寫到這里了,就給今天做一個總結吧。今天主要完成了lua-cjson在Linux下的安裝和使用,當然也有出現問題的解決。同時也測試了在Linux環境下,在Lua腳本中使用cjson工具類完成table類型的解析。最后也測試了一下如何使用C#來調用lua腳本,並執行。但是有一個事情,還沒做,就是在Windows環境下,如何在Lua腳本里使用lua-cjson來解析類型,里面涉及到的內容很多,一篇文章無法寫完,只好把相關的東西放到下一片文章吧。

天下國家,可均也;爵祿,可辭也;白刃,可蹈也;中庸不可能也


免責聲明!

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



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