<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          震驚,Java+ lua = 王炸

          共 5007字,需瀏覽 11分鐘

           ·

          2022-11-01 17:07

          推薦閱讀:阿里三面:請拿出一段體現(xiàn)你水平的代碼
          在某些業(yè)務場景下,我們可能會遇到 lua 中要調用 java 代碼情況,當然這個用 JNI 肯定是可以做到的,但是有更加方便的辦法:LuaJavaBridge(LuaJava)和 LuaJ。


          luaj 主要特征

          • 可以從 Lua 調用 Java Class Static Method

          • 調用 Java 方法時,支持 int/float/boolean/String/Lua function 五種參數(shù)類型

          • 可以將 Lua function 作為參數(shù)傳遞給 Java,并讓 Java 保存 Lua function 的引用

          • 可以從 Java 調用 Lua 的全局函數(shù),或者調用引用指向的 Lua function


          luaj 的功能很簡單,但對于集成各種 SDK 來說已經(jīng)完全滿足需求了。



          luaj 用法示例


          Java 方法原型:


          public static float getNum(float n) {    return n;}

          lua 調用示例:

          -- Java 類的名稱local className = "com/xttblog/Test"-- 調用 的Java 方法名local method = 'getNum'-- 調用 Java 方法需要的參數(shù)local n = 10local args = {     n}-- 調用 Java 方法local _, testStaticMethod = luaj.callStaticMethod(className, method, args)

          luaj 實現(xiàn)原理


          luaj 的核心目標有兩個:從 Lua 調用 Java, 從 Java 調用 Lua。整理出來就是如下幾點

          • 查找并調用指定的 Java 方法
          • 檢查調用結果,并從 Java 方法獲取返回值
          • 將 Lua function 作為參數(shù)傳遞給 Java 方法
          • 在 Java 方法中調用 Lua function

          查找并調用指定的 Java 方法

          JNI 提供了 FindClass() 方法用于查找指定的 Class,所以 luaj.callStaticMethod() 的第一個參數(shù)就是要調用的 Java Class 的完整類名稱(類名稱中的“.”要替換為“/”)。


          找到指定 Class 后,利用 JNI 的 GetStaticMethodID() 方法就可以找到這個類的指定靜態(tài)方法,前提是要提供靜態(tài)方法的名稱和簽名。


          所謂簽名,就是指Java方法的參數(shù)類型和返回類型定義。方法的簽名就是類似(Ljava/lang/String;ZZI)V這樣的一串描述,通過字節(jié)碼方式可以查看,如下示例:



          關于 Java 方法簽名的具體定義,可以參考:JNI Type Signatures。

          這里要說的是 luaj 可以根據(jù)調用參數(shù)自動猜測方法簽名所以示例中我們并沒有寫簽名。

          示例中指定參數(shù):

          local args = {n}

          luaj 根據(jù)這 個參數(shù),會構造出正確的方法簽名。

          注意:這里要說的是 Lua 里沒有辦法準確判斷一個數(shù)值是整數(shù)還是浮點數(shù),所以 luaj 在猜測方法簽名時,假定所有的數(shù)值都是浮點數(shù)。所以下面調用會報錯:

          public static int getNum(int n) {  return n;}
          -- Java 類的名稱local className = "com/xttblog/Test"-- 調用 的Java 方法名local method = 'getNum'-- 調用 Java 方法需要的參數(shù)local n = 10local args = { n}-- 調用 Java 方法local _, testStaticMethod = luaj.callStaticMethod(className, method, args)

          這樣是不行的,所以這個時候我們要自己定義簽名。

          下面給出正確的示例

          public static int getNum(int n) {  return n;}-- Java 類的名稱local className = "com/xttblog/Test"-- 調用 的Java 方法名local method = 'getNum'-- 調用 Java 方法需要的參數(shù)local n = 10local args = {     n}-- 定義簽名-- 參數(shù): [I]nteger-- 返回值: [I]ntlocal sig = "(I)I"-- 調用 Java 方法local _, testStaticMethod = luaj.callStaticMethod(className, method, args,sig)

          簽名使用“(依次排列的參數(shù)類型)返回值類型”的格式,幾個例子如下:

          簽名                                         解釋()V                             參數(shù):無,返回值:無(I)V                            參數(shù):int,返回值:無(Ljava/lang/String;)Z           參數(shù):字符串,返回值:布爾值(IF)Ljava/lang/String;          參數(shù):整數(shù)、浮點數(shù),返回值:字符串

          這里列出不同類型對應的 Java 簽名字符串:

          類型名                 類型I                       整數(shù),或者 Lua functionF                       浮點數(shù)Z                       布爾值Ljava/lang/String;      字符串V                       Void 空,僅用于指定一個 Java 方法不返回任何值


          Java 方法里接收 Lua function 的參數(shù)必須定義為 int 類型

          從 Java 方法獲取返回值


          luaj 會檢查調用結果,并從 Java 方法獲取返回值。

          luaj 調用 Java 方法時,可能會出現(xiàn)各種錯誤,因此 luaj 提供了一種機制讓 Lua 調用代碼可以確定 Java 方法是否成功調用。

          luaj.callStaticMethod()會返回兩個值:

          • 當成功時,第一個值為 true,第二個值是 Java 方法的返回值(如果有)。
          • 當失敗時,第一個值為 false,第二個值是錯誤代碼。

          下面的代碼展示了如何檢查返回結果和獲得返回值:

          public static int AddTwoNumbers(final int number1, final int number2) {  return number1 + number2;}

          Lua代碼

          local args = {2, 3}local sig = "(II)I"local ok, ret = luaj.callStaticMethod(className, "AddTwoNumbers", args, sig)
          if not ok thenprint("luaj error:", ret)elseprint("ret:", ret) -- 輸出 ret: 5end

          錯誤代碼定義如下:

          錯誤代碼                            描述-1                          不支持的參數(shù)類型或返回值類型-2                          無效的簽名-3                          沒有找到指定的方法-4                          Java 方法執(zhí)行時拋出了異常-5                          Java 虛擬機出錯-6                          Java 虛擬機出錯

          將 Lua function 作為參數(shù)傳遞給 Java 方法

          Lua 虛擬機中,Lua function 以值的形式保存。但這個值無法直接給 Java 用,所以 luaj 做了一個 Lua function 引用表。當一個 Lua function 傳遞給 Java 時,這個 function 對應的值會被存在引用表中,并獲得一個唯一的引用 ID (整數(shù))。Java 代碼拿到這個引用 ID 后,就可以很方便的調用該 Lua function 了。

          所以 Java 方法里接收 Lua function 的參數(shù)必須定義為 int 類型。

          示例:

          public static int getNum(int n) {  return n;}
          local function callback(result) ---方法內容end-- Java 類的名稱local className = "com/xttblog/Test"-- 調用 的Java 方法名local method = 'getNum'-- 調用 Java 方法需要的參數(shù)local args = { callback}-- 定義簽名-- 參數(shù): [I]nteger-- 返回值: [I]ntlocal sig = "(I)I"-- 調用 Java 方法local _, testStaticMethod = luaj.callStaticMethod(className, method, args,sig)

          另外,LuaJ 也很好用。只需引入 pom。


          ?然后直接把 lua 代碼當做 String 字符串內嵌到 Java 代碼中:

          String luaStr = "print 'hello,world!'";Globals globals = JsePlatform.standardGlobals();LuaValue chunk = globals.load(luaStr);chunk.call();

          也可以創(chuàng)建一個 login.lua 腳本,內容如下:

            --無參函數(shù)   function hello()      print 'hello'   end--帶參函數(shù)   function test(str)      print('data from java is:'..str)      return 'haha'   end

          然后,Java先載入login.lua腳本并編譯,然后再獲取指定名稱的函數(shù),無參的直接使用call()方法調用,帶參的需要通過invoke(LuaValue[])傳入?yún)?shù)表:

             String luaPath = "res/lua/login.lua"; //lua腳本文件所在路徑   Globals globals = JsePlatform.standardGlobals();//加載腳本文件login.lua,并編譯globals.loadfile(luaPath).call();//獲取無參函數(shù)helloLuaValue func = globals.get(LuaValue.valueOf("hello"));//執(zhí)行hello方法func.call();//獲取帶參函數(shù)testLuaValue func1 = globals.get(LuaValue.valueOf("test"));//執(zhí)行test方法,傳入String類型的參數(shù)參數(shù)String data = func1.call(LuaValue.valueOf("I'am from Java!")).toString();   //打印lua函數(shù)回傳的數(shù)據(jù)   Logger.info("data return from lua is:"+data);

          運行結果如下:
          hellodata from java is:I'am from Java!八月 07, 2022 5:31:25 下午 com.tw.login.tools.Logger info信息: lua return datahah

          瀏覽 35
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品成人免费视频 | 久久艹伊人 | 俺去草 | 鸡巴操穴视频 | 免费黄的在线观看中文字幕视频 |