日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

导出 C/C++ API 给 Lua 使用[转]

發布時間:2025/6/17 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 导出 C/C++ API 给 Lua 使用[转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導出 C/C++ API 給 Lua 使用

cocos2d-x 和 quick-cocos2d-x 的底層代碼都是使用 C++ 語言開發的。為了使用 Lua 腳本語言進行開發,我們利用?tolua++?工具,將大量的 C/C++ API 導出到了 Lua 中。

使用 tolua++ 的基本步驟:

  • 從 C/C++ 源代碼復制頭文件的內容到 .tolua(tolua++ 文檔中稱為 .pkg)文件中。
  • 修改 .tolua 文件內容,去掉 tolua++ 無法識別的內容,以及不需要導出到 Lua 的定義。
  • 運行 tolua++ 工具,根據 .tolua 文件生成 luabinding 接口文件(由 .cpp 文件和 .h 文件自稱)。
  • 在 AppDelegate.cpp 中加載 luabinding 文件。
  • 在 AppDelegate 初始化 Lua 虛擬機后,調用 luabinding 接口文件中的 luaopen 函數,注冊 C/C++ API。
  • 根據實踐,我們建議采用如下的方案來完成整個導出工作。

    ?

    從 C/C++ 源文件創建 .tolua 文件

    假設我們的?MyClass.h?頭文件內容如下:

    #ifndef __MY_CLASS_H_ #define __MY_CLASS_H_class MyClass { public:static void addTwoNumber(float number1, float number2);private:MyClass(void) {} };#endif // __MY_CLASS_H_

    為了便于維護,應該將 .h 文件對應的 tolua 命名為 XXX_luabinding.tolua。這樣生成的 luabinding 接口文件名就是 XXX_luabinding.cpp 和 XXX_luabinding.h,不會和已有的 C/C++ 源文件沖突。

    創建 MyClass_luabinding.tolua 文件,并修改內容為:

    class MyClass : public CCObject { public:static void addTwoNumber(float number1, float number2); };

    這里可以看到 .tolua 的內容有明顯簡化。詳細的內容修改規則,會在本文后續部分說明。

    ?

    生成 luabinding 接口文件

    quick 為了簡化這一步工作,提供了相應工具,我們只需要創建一個腳本文件來調用工具即可。

  • 創建 build_luabinding.sh 文件,內容如下:

    #!/usr/bin/env bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$DIR" OUTPUT_DIR="$DIR" MAKE_LUABINDING="$QUICK_COCOS2DX_ROOT"/bin/compile_luabinding.sh $MAKE_LUABINDING -E MyClass -d "$OUTPUT_DIR" MyClass_luabinding.tolua

    記得在命令行中 chmod 755 build_luabinding.sh,否則無法執行該腳本。

    Windows 版的批處理內容如下:

    @echo off set DIR=%~dp0 set OUTPUT_DIR=%DIR% set MAKE_LUABINDING="%QUICK_COCOS2DX_ROOT%\bin\compile_luabinding.bat" pushd cd /d "%DIR%" call %MAKE_LUABINDING% -E MyClass -d %OUTPUT_DIR% MyClass_luabinding.tolua

    注意:運行腳本前請確保已經下載了 quick-cocos2d-x,并且正確設置了 QUICK_COCOS2DX_ROOT 環境變量。環境配置請參考《入門指引》。

  • 在命令行下運行我們創建的腳本,如果一切順利,我們會看到如下輸出信息:

    creating file: MyClass_luabinding.cpp creating file: MyClass_luabinding.h// add to AppDelegate.cpp #include "MyClass_luabinding.h"// add to AppDelegate::applicationDidFinishLaunching() CCLuaStack* stack = CCScriptEngineManager::sharedManager()->getScriptEngine()->getLuaStack(); lua_State* L = stack->getLuaState(); luaopen_MyClass_luabinding(L);
  • ?

    載入 luabinding 接口文件

    打開我們的項目,將 MyClass_luabinding.cpp 和 MyClass_luabinding.h 文件加入工程。然后修改 AppDelegate.cpp 文件:

  • 在 AppDelegate.cpp 頭部區域添加:

    #include "MyClass_luabinding.h"
  • 在 AppDelegate::applicationDidFinishLaunching() 函數內添加:

    luaopen_MyClass_luabinding(L);

    注意這一行代碼應該添加在其他 luaopen 函數后面,例如:

    // register lua engine CCLuaEngine *pEngine = CCLuaEngine::defaultEngine(); CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);CCLuaStack *pStack = pEngine->getLuaStack(); lua_State* L = pStack->getLuaState();// load lua extensions luaopen_lua_extensions(L); // load cocos2dx_extra luabinding luaopen_cocos2dx_extra_luabinding(L);// thrid_party luaopen_third_party_luabinding(L);// CCBReader tolua_extensions_ccb_open(L);// MyClass luaopen_MyClass_luabinding(L);

    應該將我們的代碼追加到 tolua_extensions_ccb_open() 后面。

  • 經過上述修改后,重新編譯運行項目應該就可以在 Lua 腳本中使用我們導出的 MyClass 對象極其方法了。

    ?

    .tolua 文件內容的修改規則

    前面的 MyClass 是一個非常簡單的例子,但我們實際游戲中的 C/C++ API 可能比較復雜。在修改 .tolua 文件內容時,應該仔細閱讀以下內容。

    ?

    刪除所有無需在 Lua 中使用的內容

    導出的 API 越多,在 Lua 虛擬機中占用的符號表空間就越多。因此我們第一步要做的就是刪除所有無需在 Lua 中使用的內容。

  • 對于 enum、宏定義,如果需要導出,原文保留即可。但宏定義只能導出數值定義,例如:

    #define kCCHTTPRequestMethodGET 0 #define kCCHTTPRequestMethodPOST 1

    而非數值的宏定義無法導出,以下內容會導出失敗:

    #define kMyConstantString "HELLO"
  • 刪除所有無法識別的宏,例如 CC_DLL。

  • 刪除 C++ class 中所有非 public 的定義。

  • 刪除 C++ class 中的類成員變量。

  • 刪除 inline 關鍵詞,以及 inline function 的實現,只保留聲明。

  • ?

    處理 CCObject 繼承類

    CCObject 及其繼承類都具備“引用計數”和“自動釋放”機制。如果你的 C++ 對象是從 CCObject 繼承的,那么必須告訴 tolua++ 做相應處理,否則可能出現內存泄漏等問題。

    對于 quick,只需要在 build 腳本中通過 -E CCOBJECTS 參數指定這些 class 的名字即可。

    例如前面 MyClass 的示例中,用 -E CCOBJECTS=MyClass 告訴 tolua++ 應該將 MyClass 當作 CCObject 的繼承類進行處理。

    如果有多個類,那么每個類名之間用“,”分隔即可,例如:

    $MAKE_LUABINDING -E CCOBJECTS=MyClass,MyClass2,MyClass3 -d "$OUTPUT_DIR" MyClass_luabinding.tolua

    ?

    展開宏

    有些宏是不能直接刪除的,例如 CC_PROPERTY。對于這類宏,需要根據宏定義,將宏展開為聲明。

    CC_PROPERTY(float, m_fDuration, Duration)

    展開為:

    float getDuration(); void setDuration(float v);

    需要如此處理的宏包括:CC_PROPERTY_READONLY, CC_PROPERTY, CC_PROPERTY_PASS_BY_REF, CC_SYNTHESIZE_READONLY, CC_SYNTHESIZE_READONLY_PASS_BY_REF, CC_SYNTHESIZE, CC_SYNTHESIZE_PASS_BY_REF, CC_SYNTHESIZE_RETAIN。

    幸運的是這些宏大多只用在 cocos2d-x 基礎代碼里,我們自己的 C++ class 還是不要用這些宏了。

    ?

    處理名字空間

    如果使用了名字空間,那么在 .tolua 的頭部應該加入:

    $using namespace myname;

    這里用到的“$”符號,后續內容會原樣放入 luabinding 文件。

    ?

    添加必要的 #include 指令

    如果生成的 luabinding 接口文件無法編譯,需要檢查是否是需要 include 相應的頭文件,并添加如下代碼:

    $#include "MyClass.h"

    ?

    修改函數參數和返回值類型,去除 const 修飾符

    一些函數的參數或返回值,使用了 const 修飾符。由于 tolua++ 的限制,并不能很好的處理這類定義,所以我們要從 .tolua 文件中移除 const 修飾符。唯一例外的就是 const char* 不需要修改為 char*。

    例如:

    CCPoint convertToNodeSpace(const CCPoint& worldPoint);

    應該修改為:

    CCPoint convertToNodeSpace(CCPoint& worldPoint);

    這樣修改的原因是 tolua++ 把 const CCPoint 和 CCPoint 當做兩個不同的類型來處理。如果不做修改,那么調用函數時會報告參數類型不符。

    ?

    從 C/C++ 函數返回多個值

    如果一個函數的所有參數都是引用或指針類型,并且不是 const char*,那么在 luabinding 接口文件中,該函數會返回多個值。

    例如:

    void getPosition(float* x = 0, float* y = 0);

    在 Lua 中調用這個函數,會得到兩個返回值:

    local x, y = node:getPosition()

    ?

    將 Lua 函數傳入 C/C++

    quick 里,允許將 Lua 函數傳入 C/C++,只要求 C/C++ 函數中使用 int 做參數類型。但在 .tolua 文件里,則必須使用 LUA_FUNCTION 做參數類型。

    例如:

    static CCHTTPRequest* createWithUrlLua(int listener,const char* url,int method = kCCHTTPRequestMethodGET);

    listener 參數用于保存傳入的 Lua 函數,所以 .tolua 文件里要改寫為:

    static CCHTTPRequest* createWithUrlLua(LUA_FUNCTION listener,const char* url,int method = kCCHTTPRequestMethodGET);

    具體用法請參考 lib/cocos2dx_extra/extra/network/CCHTTPRequest 中的 createWithUrlLua() 方法。

    ?

    在 Lua 和 C/C++ 間交換二進制數據

    要從 C/C++ 返回二進制數據給 Lua,函數返回值類型必須是 int,而 .tolua 文件中修改返回值為 LUA_STRING。函數中,需要用 CCLuaStack::pushString() 將二進制數據放入 Lua stack。然后返回“需要傳遞給 Lua 的值”的數量。

    具體用法請參考 lib/cocos2dx_extra/extra/network/CCHTTPRequest 中的 getResponseDataLua() 方法。

    從 Lua 傳遞二進制數據給 C/C++ 很簡單,使用 const char* 參數類型和 int 類型參數分別指定二進制數據的指針和數據長度。

    具體用法請參考 lib/cocos2dx_extra/extra/crypto/CCCrypto 中的 decryptXXTEALua() 方法。

    ?

    更多用法

    關于利用 tolua++ 的更多用法,建議參考 lib/cocos2dx_extra 中的 CCCrypto、CCNative、CCHTTPRquest 等 class。這些 class 對 Lua 提供了良好的支持,具體用法上也覆蓋了絕大多數 C/C++ 和 Lua 交互的需求。

    - END -

    轉載于:https://www.cnblogs.com/dwjaissk/p/3476445.html

    總結

    以上是生活随笔為你收集整理的导出 C/C++ API 给 Lua 使用[转]的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。