国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

cocos2d-x C++與Lua交互

這篇具有很好參考價值的文章主要介紹了cocos2d-x C++與Lua交互。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Cocos版本: 3.10

Lua版本: 5.1.4

環(huán)境: window Visual Studio 2013


Lua


Lua作為一種腳本語言, 它的運行需要有宿主的存在,通過Lua虛擬棧進行數(shù)據(jù)交互。

它的底層實現(xiàn)是C語言,C語言封裝了很多的API接口,使得C/C++與Lua之間可以很方便的通信交互。

Lua的官網(wǎng): https://www.lua.org/

在cocos2dx中, Lua與C++的交互是通過**tolua++**進行的,**tolua++**實質(zhì)上是對Lua C API的一層封裝。

通過tolua++ 設定的接口,使得Lua很方便的調(diào)用C++提供的 cocos API接口。


Lua的運行需要有宿主的存在,在cocos2d-x中,C++可以作為Lua的宿主, 而Lua運行的時候需要通過虛擬棧進行數(shù)據(jù)交互,這個運行的環(huán)境,通常被稱為Lua_State。

Lua虛擬棧

棧的特點是先進后出的, 在Lua的虛擬棧中它有著如下的特點:

  • 棧中數(shù)據(jù)通過索引進行獲取數(shù)據(jù)
  • 索引的數(shù)值可以為正數(shù),也可為負數(shù); 正數(shù)為1的永遠表示棧底,負數(shù)為-1的永遠表示棧頂

如下圖所示(圖片來源:Lua調(diào)用原理展示):

cocos2d-x C++與Lua交互,cocos2d-x,cocos2d)

假設我們想使用C++訪問Lua文件中的數(shù)據(jù)

-- test.lua
str = "Get Lua Data Sucess!!!"

function Add(num1, num2)
    return num1 + num2
end 

C++獲取Lua文件中的字符串為例,其數(shù)據(jù)交互的流程是:

cocos2d-x C++與Lua交互,cocos2d-x,cocos2d

  1. C/C++將參數(shù)str放入Lua棧的棧頂

  2. Lua從棧中獲取參數(shù)str,并將棧頂置為空

  3. Lua從全局表中查找參數(shù)str對應的數(shù)據(jù)

  4. 全局表將參數(shù)str的數(shù)據(jù)反饋給Lua

  5. Lua將參數(shù)str的返回值放入堆棧中,此時返回值位于棧頂

  6. C++從棧中獲取數(shù)據(jù)


C++調(diào)用Lua需要進行環(huán)境配置:

1. 新建項目,選擇Empty Project,在項目的Source Files新增.cpp文件
2. 若有Lua的相關環(huán)境,可將Lua/5.1目錄下的include,lib文件夾拷貝到與.cpp文件同目錄下
若無,則推薦LuaForWindows
其網(wǎng)址為:http://files.luaforge.net/releases/luaforwindows/luaforwindows
它會自動配置lua的環(huán)境,并安裝SciTE工具相關,以后就可以在控制臺,SciTE輸入lua相關代碼進行調(diào)試

屬性配置,打開項目屬性:
1. C/C++ -> General -> Additional Include Directories 將include目錄添加進去
2. Linker -> General -> Additional Library Directories 將lib目錄添加進去
3. 再通過Linker -> Input -> Additional Dependencies 添加lua5.1.lib, lua51.lib

示例代碼:

#include <iostream>
#include <string.h>

extern "C" {
// 提供了Lua的基本函數(shù),在lua.h中的函數(shù)均已"lua_"為前綴
#include "lua.h"
// 定義lua的標準庫函數(shù),比如table, io, math等
#include "lualib.h"
// 提供了輔助庫相關,以"luaL_"為前綴
#include "lauxlib.h"    
}

void main(){
    // 創(chuàng)建lua環(huán)境,并加載標準庫
    lua_State* pL = lua_open();
    luaL_openlibs(pL);

    // 加載lua文件,返回0表示成功
    int code = luaL_loadfile(pL, "test.lua");
    if (code != 0){
        return;
    }

    // 執(zhí)行l(wèi)ua文件,參數(shù)分別為,lua環(huán)境,輸入?yún)?shù)個數(shù),返回值個數(shù)
    lua_call(pL, 0, 0);

    // 重置棧頂索引,設置為0表示棧清空
    lua_settop(pL, 0);

    // ------------- 讀取變量 -------------
    //lua_getglobal 主要做了這么幾件事: 將參數(shù)壓入棧中,lua獲取參數(shù)的值后再將返回的結(jié)果壓入棧中
    lua_getglobal(pL, "str");
    // 判定棧頂值類型是否為string,返回1表示成功,0表示失敗
    int isStr = lua_isstring(pL, 1);
    if (isStr == 1) {
        // 獲取棧頂值,并將lua值轉(zhuǎn)換為C++類型
        std::string str = lua_tostring(pL, 1);
        std::cout << "str = " << str.c_str() << std::endl;
    }

    // ------------- 讀取函數(shù) -------------
    lua_getglobal(pL, "Add");
    // 將函數(shù)所需要的參數(shù)入棧
    lua_pushnumber(pL, 1);            // 壓入第一個參數(shù)
    lua_pushnumber(pL, 2);            // 壓入第二個參數(shù)
    
    /*
    lua_pcall與lua_call類似,均用于執(zhí)行l(wèi)ua文件,其方法分別為:
    void lua_call(lua_State *L, int nargs, int nresults);
    int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc);
    兩者的區(qū)別在于:
        前者在出現(xiàn)錯誤,程序會崩潰。后者多了一個errfunc索引,用于準確定位錯誤處理函數(shù)。
        函數(shù)執(zhí)行成功返回0,失敗后可通過獲取棧頂信息獲取錯誤數(shù)據(jù)
    兩者的共同之處在于:
        會根據(jù)nargs將參數(shù)按次序入棧,并根據(jù)nresults將返回值按次序填入棧中
        若返回值結(jié)果數(shù)目大于nresults時,多余的將被丟棄;若小于nresults時,則按照nil補齊。
    */
    int result = lua_pcall(pL, 2, 1, 0);
    if (result != 0) {
        const char *pErrorMsg = lua_tostring(pL, -1);
        std::cout << "ERROR:" << pErrorMsg << std::endl;
        lua_close(pL);
        return;
    }

    /*
    此處的棧中情況:
    ------------- 棧頂 -------------
    正索引 負索引   類型       返回值
    2     -1      number    3
    1     -2      string    "Get Lua Data Sucess!!!"
    ------------- 棧底 -------------
    因此如下的索引獲取數(shù)字索引可以使用-1或者2
    */
    int isNum = lua_isnumber(pL, -1);
    if (isNum == 1) {
        double num = lua_tonumber(pL, -1);
        std::cout << "num = " << num << std::endl;
    }
    
    // 關閉state環(huán)境,即銷毀Lua_State對象,并釋放Lua動態(tài)分配的空間
    lua_close(pL);

    system("pause");
}

注意:

  • C++在獲取不同文件下的方法時,在通過include引用后,然后就直接調(diào)用
  • Lua通過luaL_loadfile進行加載,然后等 lua_call/lua_pcall執(zhí)行后才能獲取數(shù)據(jù)

Lua這么處理的原因在于: 全局變量表中是不會存儲相關數(shù)據(jù)的


Lua C API


這里簡要說明下常用的API相關,有助于對了解后面的**tolua++**有幫助。 主要方法有:

/*
獲取棧頂索引即棧中元素的個數(shù),因為棧底為1,所以棧頂索引為多少,就代表有多少個元素
*/
int lua_gettop(lua_State *L);

/*
將棧頂索引設置為指定的數(shù)值
若設置的index比原棧頂高,則以nil補足。若index比原棧頂?shù)?,高出的部分舍棄?比如: 棧中有8個元素,若index為7,則表示刪除了一個棧頂?shù)脑亍H鬷ndex為0,表示清空棧
注意: index為正數(shù)表示相對于棧底設置的,若為負數(shù)則相對于棧頂而設置的
*/
void lua_settop(lua_State *L, int index);

/*
將棧中索引元素的副本壓入棧頂
比如:從棧底到棧頂,元素狀態(tài)為10,20,30,40;若索引為3則元素狀態(tài)為:10,20,30,40,30
類似的還有:
lua_pushnil: 壓入一個nil值
lua_pushboolean: 壓入一個bool值
lua_pushnumber: 壓入一個number值
*/
void lua_pushvalue(lua_State *L, int index);

/*
刪除指定索引元素,并將該索引之上的元素填補空缺
比如:從棧底到棧頂,元素狀態(tài)為10,20,30,40;若索引為-3則元素狀態(tài)為10,30,40
*/
void lua_remove(lua_State *L, int index);

/*
將棧頂元素替換索引位置的的元素
比如:從棧底到棧頂,元素狀態(tài)為10,20,30,40,50;若索引為2則,元素狀態(tài)為10,50,30,40
即索引為2的元素20被棧頂元素50替換
*/
void lua_replace(lua_State *L, int index);

/*
獲取棧中指定索引元素的類型,若失敗返回類型LUA_TNONE。其它類型有:
LUA_TBOOLEAN, LUA_TNUMBER, LUA_TSTRING, LUA_TTABLE
LUA_TFUNCTION, LUA_USERDATA等
*/
int lua_type(lua_State *L, int idx);

/*
檢測棧中元素是否為某個類型,成功返回1,失敗返回0; 類似的還有:
lua_isnumber, lua_isstring, lua_iscfunction, lua_isuserdata
*/
int lua_isXXX(lua_State *L, int index);

// 將棧中元素轉(zhuǎn)換為C語言指定類型
lua_Number lua_tonumber(lua_State *L, int idx);
lua_Integer lua_tointeger(lua_State *L, int idx);
int lua_toboolean(lua_State *L, int idx);
const char* lua_tolstring(lua_State *L, int idx, size_t *len);
lua_CFunction lua_tocfunction(lua_State *L, int idx);
void* lua_touserdata(lua_State *L, int idx);

下面我們說下cocos2d-x 對Lua的封裝相關。


cocos Lua框架

Lua在cocos引擎封裝相關,它主要被放在cocos引擎的libluacocos2d

cocos2d-x C++與Lua交互,cocos2d-x,cocos2d

  • auto: 使用tolua++工具自動生成的C++代碼相關

  • **manual:**放置了cocos擴展的一些功能,比如LuaEngine, LuaStack, LuaBridge等

  • luajit: 高效版的lua庫,額外添加了lua沒有的cocos庫,并在對浮點計算,循環(huán)等進行了優(yōu)化

  • luasocket: 網(wǎng)絡庫相關

  • tolua: tolua++庫相關,實質(zhì)是對Lua C庫進行的再封裝

  • xxtea: cocos2d-x 自帶的加密相關,目前項目使用的較少,很容易被破解

Lua的在引擎中的封裝,主要是:

  • LuaEngine 封裝的對Lua的管理引擎類
  • Lua_Stack 對Lua運行環(huán)境Lua_State的封裝,LuaEngine主要管理的就是Lua_Stack

項目啟動

關于LuaEngine的初始化,主要在項目啟動的時候初始化的,它僅僅是項目啟動的一個小的環(huán)節(jié)。

如果想了解引擎的整個啟動流程,可參考博客:cocos2dx 的啟動和結(jié)束流程

而對于LuaEngine的啟動,可以簡單的分為三個步驟:

  1. 初始化LuaEngine,通過 LuaStack 獲取 LuaState 運行環(huán)境
  2. 通過**tolua++**提供的接口,將C++ 不同的模塊進行注冊
  3. 執(zhí)行Lua腳本

其主要代碼實現(xiàn)在:

bool AppDelegate::applicationDidFinishLaunching() {
    // 初始化LuaEngine
  	// 在getInstance中會初始化LuaStack,LuaStack初始化Lua環(huán)境相關
    auto engine = LuaEngine::getInstance();
    // 將LuaEngine添加到腳本引擎管理器ScriptEngineManager中
    ScriptEngineManager::getInstance()->setScriptEngine(engine);
    // 獲取Lua環(huán)境
    lua_State* L = engine->getLuaStack()->getLuaState();
    // 注冊額外的=C++提供的API模塊相關
    lua_module_register(L);
    register_all_packages();
    // 設置cocos自帶的加密相關
    LuaStack* stack = engine->getLuaStack();
    stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));

    // 執(zhí)行Lua腳本文件
    if (engine->executeScriptFile("main.lua")) {
        return false;
    }
    return true;
}

LuaEngine初始化

通過LuaEngine::getInstance(),我們了解下**LuaStack::init()**的相關實現(xiàn)

extern "C" {
#include "lua.h"             
#include "tolua++.h"    
#include "lualib.h"         
#include "lauxlib.h"
}

bool LuaStack::init(void)
{
    // 初始化Lua環(huán)境并打開標準庫
    _state = lua_open();     
    luaL_openlibs(_state);
    toluafix_open(_state);

    // 注冊全局函數(shù)print到lua中,它會覆蓋lua庫中的print方法
    const luaL_reg global_functions [] = {
        {"print", lua_print},
        {"release_print",lua_release_print},
        {nullptr, nullptr}
    };
    // 注冊全局變量
    luaL_register(_state, "_G", global_functions);

    // 注冊cocos2d-x引擎的API到lua環(huán)境中
    g_luaType.clear();
    register_all_cocos2dx(_state);
    // ...

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    // 導入android下調(diào)用java相關API
    LuaJavaBridge::luaopen_luaj(_state);
#endif
    addLuaLoader(cocos2dx_lua_loader);
    return true;
} 

針對于addLuaLoader,它是Lua的加載器,主要將 cocos2dx_lua_loader 方法添加到Lua全局變量package下的loaders成員中。

當Lua通過 requires加載腳本時,Lua會借助package下的loaders中的加載器 cocos2dx_lua_loader 加載。

該加載器支持我們自定義設置搜索路徑相關,且拓展實現(xiàn)對腳本的加密解密相關??聪滤膶崿F(xiàn):

extern "C" {
  int cocos2dx_lua_loader(lua_State *L) {
    // 后綴為luac和lua
    static const std::string BYTECODE_FILE_EXT    = ".luac";
    static const std::string NOT_BYTECODE_FILE_EXT = ".lua";
    // require傳入的要加載的文件名,比如:require "cocos.init" 下的"cocos.init"
    std::string filename(luaL_checkstring(L, 1));
    // 去掉后綴名".luac"或“.lua”
    size_t pos = filename.rfind(BYTECODE_FILE_EXT);
    if (pos != std::string::npos) {
      filename = filename.substr(0, pos);
    } else { 
      pos = filename.rfind(NOT_BYTECODE_FILE_EXT);
      if (pos == filename.length() - NOT_BYTECODE_FILE_EXT.length()) {
        filename = filename.substr(0, pos);
      }
    }
    // 將"."替換為"/"
    pos = filename.find_first_of(".");
    while (pos != std::string::npos) {
      filename.replace(pos, 1, "/");
      pos = filename.find_first_of(".");
    }

    Data chunk;
    std::string chunkName;
    FileUtils* utils = FileUtils::getInstance();
    // 獲取package.path的變量
    lua_getglobal(L, "package");
    lua_getfield(L, -1, "path");
    // 通過package.path獲取搜索路徑相關,該路徑為模版路徑,格式類似于:
    // ?; ?.lua; c:\windows\?;  /usr/local/lua/lua/?/?.lua 以“;”作為分割符
    std::string searchpath(lua_tostring(L, -1));
    lua_pop(L, 1);
    size_t begin = 0;
    size_t next = searchpath.find_first_of(";", 0);
    // 遍歷package.path中的所有路徑,查找文件是否存在,存在則通過getDataFromFile讀取數(shù)據(jù)
    do {
      if (next == std::string::npos)
        next = searchpath.length();
      std::string prefix = searchpath.substr(begin, next);
      if (prefix[0] == '.' && prefix[1] == '/') {
        prefix = prefix.substr(2);
      }

      pos = prefix.find("?.lua");
      // 將?替換為文件名,獲取搜索路徑名,比如:?.lua替換為cocos/init.lua
      chunkName = prefix.substr(0, pos) + filename + BYTECODE_FILE_EXT;
      if (utils->isFileExist(chunkName)) {
        chunk = utils->getDataFromFile(chunkName);
        break;
      } else {
        chunkName = prefix.substr(0, pos) + filename + NOT_BYTECODE_FILE_EXT;
        if (utils->isFileExist(chunkName)) {
          chunk = utils->getDataFromFile(chunkName);
          break;
        }
      }
      // 指定搜素路徑下不存在該文件,則下一個
      begin = next + 1;
      next = searchpath.find_first_of(";", begin);
    } while (begin < (int)searchpath.length());

    // 判定文件內(nèi)容是否獲取成功
    if (chunk.getSize() > 0) {
      // 加載文件
      LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
      stack->luaLoadBuffer(L, reinterpret_cast<const char*>(chunk.getBytes()),
                           static_cast<int>(chunk.getSize()), chunkName.c_str());
    } else {
      CCLOG("can not get file data of %s", chunkName.c_str());
      return 0;
    }
    return 1;
  }
}    

這個的實現(xiàn)其實就是Lua語言關于require實現(xiàn)的本質(zhì),比如:

  • Cocos2dx 是如何實現(xiàn)搜索指定的Lua文件的
  • Lua通過require是如何檢索引用文件的
  • 關于Lua文件查找不到,報錯的路徑信息是如何獲取的

想了解更多內(nèi)容,參考:lua 之 require

繼續(xù)代碼研究,看下luaLoadBuffer的實現(xiàn):

nt LuaStack::luaLoadBuffer(lua_State *L, const char *chunk, int chunkSize, const char *chunkName) {
  int r = 0;
  // 判定是否加密,若lua腳本加密,則解密后在加載腳本文件
  // luaL_loadbuffer 用于加載并編譯Lua代碼,并將其壓入棧中
  if (_xxteaEnabled && strncmp(chunk, _xxteaSign, _xxteaSignLen) == 0) {
    // decrypt XXTEA
    xxtea_long len = 0;
    unsigned char* result = xxtea_decrypt((unsigned char*)chunk + _xxteaSignLen,
                                          (xxtea_long)chunkSize - _xxteaSignLen,
                                          (unsigned char*)_xxteaKey,
                                          (xxtea_long)_xxteaKeyLen,
                                          &len);
    skipBOM((const char*&)result, (int&)len);
    r = luaL_loadbuffer(L, (char*)result, len, chunkName);
    free(result);
  } else {
    skipBOM(chunk, chunkSize);
    r = luaL_loadbuffer(L, chunk, chunkSize, chunkName);
  }

  // 判定內(nèi)容是否存在錯誤
  #if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0
  if (r) {
    switch (r) {
      case LUA_ERRSYNTAX: 
        // 語法錯誤
        CCLOG("[LUA ERROR] load \"%s\", error: syntax error during pre-compilation.", chunkName);
        break;
      case LUA_ERRMEM:
        // 內(nèi)存分配錯誤
        CCLOG("[LUA ERROR] load \"%s\", error: memory allocation error.", chunkName);
        break;
      case LUA_ERRRUN: 
        // 運行錯誤
        CCLOG("[LUA ERROR] load \"%s\", error: run error.", chunkName);
        break;
      case LUA_ERRFILE:
        // 文件錯誤
        CCLOG("[LUA ERROR] load \"%s\", error: cannot open/read file.", chunkName);
        break;
      case LUA_ERRERR:           
        // 運行錯誤處理函數(shù)時發(fā)生錯誤
        CCLOG("[LUA ERROR] load \"%s\", while running the error handler function.", chunkName);
      default:
        // 未知錯誤
        CCLOG("[LUA ERROR] load \"%s\", error: unknown.", chunkName);
    }
    // 通過lua的堆棧,獲取棧頂?shù)腻e誤信息,將錯誤日志打印出來(-1永遠表示棧頂)
    const char* error = lua_tostring(L, -1);
    CCLOG("[LUA ERROR] Error Result: %s", error);
    lua_pop(L, 1);
  }
  #endif
  return r;
}

這里對Lua做的事情主要是:

  • 檢測Lua是否加密,如果是,則進行解密; 否則加載并編譯Lua代碼
  • 如果是測試版本,會對Lua的內(nèi)容進行安全檢測。

最后我們梳理下關于LuaEngine對Lua的操作流程:

  • 獲取LuaEngine的接口,調(diào)用LuaStack對Lua所需要的環(huán)境進行初始化
  • 通過addLuaLoader將Lua的變量等信息添加到加載器中進行解析
  • 解析文件后,通過loadBuffer加載Lua文件數(shù)據(jù)并進行安全檢測。

到這里Lua的文件數(shù)據(jù)相關算是初始化成功了。


tolua++

**tolua++**是cocos官方提供的一個將C++代碼相關轉(zhuǎn)換為指定格式文件的工具,用于實現(xiàn)Lua對C++的調(diào)用, 簡單的看下引擎在項目啟動中關于tolua++封裝的接口相關:

TOLUA_API int register_all_cocos2dx(lua_State* tolua_S)
{
    tolua_open(tolua_S);
    
    tolua_module(tolua_S,"cc",0);
    tolua_beginmodule(tolua_S,"cc");

    lua_register_cocos2dx_Ref(tolua_S);
    lua_register_cocos2dx_Node(tolua_S);

    // 省略...
    tolua_endmodule(tolua_S);
    return 1;
}

int lua_register_cocos2dx_Ref(lua_State* tolua_S)
{
    tolua_usertype(tolua_S,"cc.Ref");
    tolua_cclass(tolua_S,"Ref","cc.Ref","",nullptr);
    // tolua_function 表示對應的Ref所持有的public接口相關
    tolua_beginmodule(tolua_S,"Ref");
        tolua_function(tolua_S,"release",lua_cocos2dx_Ref_release);
        tolua_function(tolua_S,"retain",lua_cocos2dx_Ref_retain);
        tolua_function(tolua_S,"getReferenceCount",lua_cocos2dx_Ref_getReferenceCount);
    tolua_endmodule(tolua_S);
    std::string typeName = typeid(cocos2d::Ref).name();
    g_luaType[typeName] = "cc.Ref";
    g_typeCast["Ref"] = "cc.Ref";
    return 1;
}

**tolua++**的特點就是開頭必帶前綴: tolua_

  • tolua_usertype 用于聲明一個自定義的類型,將其注冊到Lua中
  • tolua_cclass 聲明一個C++類,并將其注冊到Lua中。參數(shù)中的第一個是Lua中的類名,第二個是C++類名,第三個是父類名,第四個是模板參數(shù)(可選),第五個是模板名(可選)
  • tolua_beginmodule/tolua_endmodule 用于定義一個模塊,并將接口函數(shù)注冊到該模塊中
  • tolua_function 將一個C++類的成員函數(shù)或靜態(tài)函數(shù)注冊為Lua中的函數(shù), 方便調(diào)用

任意看一段函數(shù)的實現(xiàn):

int lua_cocos2dx_Ref_getReferenceCount(lua_State* tolua_S) {
  int argc = 0;
  cocos2d::Ref* cobj = nullptr;
  bool ok  = true;

  #if COCOS2D_DEBUG >= 1
  tolua_Error tolua_err;
  #endif

  // 從Lua棧中獲取cocos對象類型,是否為cc.Ref
  #if COCOS2D_DEBUG >= 1
  if (!tolua_isusertype(tolua_S,1,"cc.Ref",0,&tolua_err)) goto tolua_lerror;
  #endif
  // 將數(shù)據(jù)轉(zhuǎn)換為Ref對象,若失敗則提示:無效的對象
  cobj = (cocos2d::Ref*)tolua_tousertype(tolua_S,1,0);
  #if COCOS2D_DEBUG >= 1
  if (!cobj) 
  {
    tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Ref_getReferenceCount'", nullptr);
    return 0;
  }
  #endif

  // 獲取參數(shù)數(shù)目,-1的原因在于對象類型Ref也在棧中
  argc = lua_gettop(tolua_S)-1;
  if (argc == 0) {
    if(!ok)
    {
      tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Ref_getReferenceCount'", nullptr);
      return 0;
    }
    unsigned int ret = cobj->getReferenceCount();
    tolua_pushnumber(tolua_S,(lua_Number)ret);
    return 1;
  }
  luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Ref:getReferenceCount",argc, 0);
  return 0;
}

其他的cocos2d-x提供的Lua可調(diào)用方法不再贅述,與之類似。


結(jié)語

前面的內(nèi)容將cocos2dx對Lua的封裝,以及tolua++的使用,說了很多,主要原因在于:

  • 官方提供的一些接口,僅支持在C++中使用,不支持在Lua中使用,比如骨骼動畫中的一些復雜邏輯處理
  • 項目的拓展需要有底層的支持
  • 項目如果將cocosStudio替換為FairyGUI,需要了解這些。

最后祝大家學習生活愉快!文章來源地址http://www.zghlxwxcb.cn/news/detail-713994.html

到了這里,關于cocos2d-x C++與Lua交互的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 綁定證書的cocos2d程序如何對wss長連接抓包

    綁定證書的cocos2d程序如何對wss長連接抓包

    點擊上方 ↑ ↑ ↑ 藍字[ 協(xié)議分析與還原 ]關注我們 “ ?解決在應用內(nèi)綁定了證書的cocos2d應用wss長連接抓包的問題。 ” 在分析應用的過程中,不可避免地需要抓包。 沒加密的還好說,隨便找個工具抓下就可以分析了,有些應用數(shù)據(jù)使用tls加密了,但用的是系統(tǒng)內(nèi)置的證書,

    2024年02月05日
    瀏覽(26)
  • cocos2d-x 3.17 推箱子 0.1

    cocos2d-x 3.17 推箱子 0.1

    此版本為推箱子游戲的基礎版本, 后續(xù)添加如下功能 人物動畫 TiledMap 解析 射線碰撞檢測 下一步提示, C++算法解析 道具, 可以回退一步 通過 cocos 命令新建一個項目, 將本項目的 Reources 目錄和 Classes 目錄復制過去即可 使用圖集繪制 Sprite , 然后手動處理碰撞檢測 游戲?qū)W論著翻譯

    2024年02月08日
    瀏覽(25)
  • 《入門級-Cocos2d 4.0塔防游戲開發(fā)》---第二課:游戲加載界面開發(fā)

    《入門級-Cocos2d 4.0塔防游戲開發(fā)》---第二課:游戲加載界面開發(fā)

    目錄 一、開發(fā)環(huán)境介紹 二、開發(fā)內(nèi)容 2.1 修改窗口的大小。 2.2 添加加載場景相關代碼 2.3 添加資源 三、顯示效果 四、知識點 ?4.1?Sprite 4.2 定時器 操作系統(tǒng):UOS1060專業(yè)版本。 cocos2dx:版本 環(huán)境搭建教程: 統(tǒng)信UOS下配置安裝cocos2dx開發(fā)環(huán)境_三雷科技的博客-CSDN博客 ? ? ? ?游

    2024年02月15日
    瀏覽(38)
  • 使用“Cocos引擎”創(chuàng)建的cpp工程如何在VS中調(diào)試Cocos2d-x源碼

    使用“Cocos引擎”創(chuàng)建的cpp工程如何在VS中調(diào)試Cocos2d-x源碼

    前段時間Cocos2d-x更新了一個Cocos引擎,這是一個集合源碼,IDE,Studio這一家老小的整合包,我們可以使用這個Cocos引擎來創(chuàng)建我們的項目。 在Cocos2d-x被整合到Cocos引擎之前,我們可以不那么方便地在我們創(chuàng)建的工程里調(diào)試Cocos2d-x的代碼,當我們使用了整合后的Cocos引擎,調(diào)試

    2024年02月12日
    瀏覽(23)
  • win10 vs2022 搭建 cocos2d-x 3.17 開發(fā)環(huán)境

    win10 vs2022 搭建 cocos2d-x 3.17 開發(fā)環(huán)境

    https://cocos2d-x.org/download/ 也可以在 github 下載 https://github.com/cocos2d/cocos2d-x/tags https://docs.cocos2d-x.org/cocos2d-x/v3/zh/ https://docs.cocos2d-x.org/api-ref/cplusplus/v3x/index.html 需要 python2 , 安裝后可以用 python2 的絕對路徑運行 cocos 的 setup.py 如何沒有把 python2 加入到環(huán)境變量, 可以修改引擎路徑下

    2024年02月08日
    瀏覽(26)
  • 如何將cocos2d-x js打包部署到ios上 Mac M1系統(tǒng)

    如何將cocos2d-x js打包部署到ios上 Mac M1系統(tǒng)

    項目環(huán)境 cocos2d-x 3.13 xcode 12 mac m1 big sur 先找到你的項目 使用xcode軟件打開上面這個文件 打開后應該是這個樣子 執(zhí)行編譯運行就好了 可能會碰到的錯誤 在xcode11版本以上都會有這個錯誤,這是因為iOS11+廢棄了system。 將上面代碼修改為 解決方案地址 remove \\\"system\\\" usage by minggo ·

    2024年02月22日
    瀏覽(21)
  • # Lua與C++交互(二)———— 交互

    # Lua與C++交互(二)———— 交互

    基礎調(diào)用 再來溫習一下 myName = “beauty girl” C++想要獲取myName的值,根據(jù)規(guī)則,它需要把myName壓入棧中,這樣lua就能看到; lua從堆棧中獲取myName的值,此時棧頂為空; lua拿著myName去全局表中查找與之對應的字符串; 全局表找到,并返回\\\"beauty girl\\\"; lua把\\\"beauty girl\\\"壓入棧中;

    2024年02月11日
    瀏覽(26)
  • Lua與C++交互

    Lua與C++交互

    1、lua和c++交互機制是基于一個虛擬棧,C++和lua之間的所有數(shù)據(jù)交互都通過這個虛擬棧來完成,無論何時C++想從lua中調(diào)用一個值,被請求的值將會被壓入棧,C++想要傳遞一個值給Lua,首選將整個值壓棧,然后就可以在Lua中調(diào)用。 2、lua中提供正向和反向索引,區(qū)別在于證書永遠

    2024年02月08日
    瀏覽(23)
  • cocos2dx學習之UIListView.cpp

    /**************************************************************************** Copyright (c) 2013-2017 Chukong Technologies Inc. http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \\\"Software\\\"), to deal in the Software without restriction, including witho

    2024年02月11日
    瀏覽(28)
  • cocos2dx學習之UIListView.h

    /**************************************************************************** Copyright (c) 2013-2017 Chukong Technologies Inc. http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \\\"Software\\\"), to deal in the Software without restriction, including witho

    2024年02月11日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包