SLua 中使用 Lua 5.3 的編譯工程


2016-03-05 更新:

之前編譯的庫,在 Android 下 Lua_Number 和 Lua_Integer 被編譯為了32位,導致從 C# 到 Lua 過程中有64位到32位整型轉換會出現溢出出錯,出現異常大的負整數。

以下修改或是之前遺漏的部分均使用紅色表示。


2016-11-21 更新:

之前編譯的庫都是用的是 32位的 NDK(當時vs2015還不支持最新的64位ndk),如果你是用64位的 NDK 編譯請注意兼容性問題;其二請注意安卓打包的庫目錄問題,安卓庫 "libs"目錄下對應於不同的cpu目錄:

ARM 32: "armeabi-v7a"

ARM 64: "arm64-v8a"

x86 32: "x86"

x86 64: "x86_64"


  我們項目將 SLua 中的 Lua 核心升級為了 5.3.2,添加了 LPeg 和 sproto(和服務器兼容)。

整個工程直接分別創建了 Mac 和 IOS 的 XCode 工程,以及 Windows 和 Android 的 VS2015工程,vs 支持 clang 和 gcc 后,可以直接創建 Android NDK 工程。

  安裝 vs2015 的過程中,可以選擇安裝 Android 的支持,但是 NDK 以及其他工具的安裝需要從谷歌下載,會導致這些組件安裝失敗,所以只能安裝完成后,手動安裝 NDK。

  vs2015 只支持 NDK r10e 32位,使用更高版本將無法使用 clang,因為 vs2015默認且只支持 clang 3.6,具體請閱讀這里。各個 Android 需求工具的安裝默認路徑,請參考這里

  一個簡單的辦法是:將下載好的 NDK 放置在:“C:\ProgramData\Microsoft\AndroidNDK”,或其他地方,然后修改注冊表:“HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\Setup\VS\SecondaryInstaller\AndroidNDK”(沒有則新建),然后新建項:“NDK_HOME”,設置值為 NDK 的安裝路徑即可完成。再次編譯 NDK 工程則不會出現 "NDK_ROOT" 未定義的情況。

  最簡單的辦法是:在安裝時不勾選 Android SDK,NDK,自己單獨下載,安裝 vs2015 完畢后,在 工具 -> 選項 -> Cross Platform -> C++ -> Android 一欄修改路徑即可。

  使用 vs2015 編譯 Android 版本 slua 需要注意的幾個地方:

  • 目前主流的 ARM 處理器都是帶浮點處理單元的,即:“armeabi-v7a”,需要在 ARM 架構的配置中加入宏定義:“__ARM_ARCH_7A__”(實際在 vs2015 中編譯的最低版本也是 armv7,不顯式指定此宏也可以)
  • 目前 支持 c99 的 NDK 至少為:“Jelly Bean 4.3.x,(android-18)”(屬性頁中的目標 API 級別),如果想兼容更低版本的 api,需要添加宏定義:“LUA_USE_C89”,否則會出現 error : undefined reference to 'log2' 錯誤,(屬性頁-> C/C++ -> 語言 -> C語言標准,不需要設置成 -std=c89,保持默認值:“默認”,可能依然導致編譯錯誤。);(此處注意:一旦使用 LUA_USE_C89,那么 Lua_Number 和 Lua_Integer 就會被編譯為32位,具體請參考 luaconf.h 中的代碼,slua 中 lua_pushinteger 導出接口的定義默認使用的是 Int64,所以存在一個類型轉換和溢出問題,你會發現無論你怎么調用 lua_pushinteger 到了 lua 端,數據都是錯的,很可能是一個大的負整數,這就是我找了好幾天才發現的錯誤,一個大坑。當然,你也可以在 slua 的 luadll.cs 中將 lua_pushinteger 導出接口的定義改為 Int32 應該也能修復,不過我沒有試驗並強烈建議使用 64 位整形的 Lua。)(2017-07-09更新:后來查看了 XLua 的工程編譯並知道了,其實 log2 是 c99 的新函數,在 c98 中 lua 是通過兩步運算模擬的,c99 中直接使用 log2 運算效率更高,所以如果為了支持 Android api 更低級別,只需要刪除 math_log 中
    #if !defined(LUA_USE_C89)
        if (base == 2.0) res = l_mathop(log2)(x); else
    #endif

    這一小段代碼即可,影響就是在 log2 的運算中,效率稍低,但是兼容性更好了。)

  • 可能編譯 Lua 會出現錯誤:error : no member named 'decimal_point' in 'struct lconv',你可以修改 luaconf.h 中將
    #define lua_getlocaledecpoint()        (localeconv()->decimal_point[0])

    修改為:

    #define lua_getlocaledecpoint()        ('.')

    但是這樣修改了源文件會影響其他平台,所以更好的方式是,在工程屬性頁 -> C/C++ -> 命令行 -> 其他選項 中加入:-D "lua_getlocaledecpoint()=('.')" ,(引號也是內容一部分),這樣修改僅限於 Android 平台編譯;

  • 如果出現各種連接錯誤:error : undefined reference to 'xxx',xxx 為各種數學函數 sin, cos 等等,需要給連接器增加 -lm 選項,動態查找鏈接接口:工程屬性頁 -> 鏈接器 -> 命令行 -> 其它選項 中加入:-lm 即可。
  • 同時需要在工程 Debug 配置中加入宏定義:"LPEG_DEBUG"
  • Mac 版本編譯 Debug 版本,由於代碼的一些書寫(函數定義和使用)不符合 c99 書寫標准,需要修改才能編譯通過;
  • Mac 版本編譯的額外鏈接選項 Other Linker Flags 需要加入:“-undefined dynamic_lookup”;
  • 默認 Lua 的異常使用 longjmp,如果編譯為 c++ 會自動轉換為 try-catch,如果在c++工程中編譯 c 代碼,由於已經定義 _cplusplus,LUAI_THROW 會被展開為 try,出現編譯錯誤的話可以考慮添加宏:LUA_USE_LONGJMP。

  編譯工程 SLua + Lua 5.3.2 + LPeg 1.0.0 + sproto 的 GitHub 地址:https://github.com/yaukeywang/slua-503-build

  后續:由於 premake5 目前對 vs2015 的支持還不完整,打算利用業余時間擴展 premake5,同時將改工程修改為 premake5 工程並提交到 github。


免責聲明!

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



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