cocos2d-x 3.0開始, lua binding使用tolua++方式自動繫結底層c++類到lua層,使使用者能夠用lua方式呼叫引擎各種介面。但是使用者還是希望手動繫結某些自定義類,所以接下來的內容將一步一步講解如何手動將自定義c++類繫結到lua。
首先,定義乙個類foo,這個類就是接下來要繫結到lua的類。
注意:所有c++類檔案必須放在 classes 資料夾裡,所有lua檔案必須放在 resources 資料夾裡。
在 fun.h 標頭檔案中新增如下**:
#include這個類有三個函式,建構函式、add函式和析構函式。作用是輸出不同字串,以判斷各函式是否被呼叫。#include
class
foostd
::string
add(
inta
,intb)
~foo
()private
:std
::string
name
;};
開始前,先了解下繫結c++類的一些基本原理。
首先建立乙個userdata來存放c++類物件指標,然後給userdata新增元表,用index元方法對映c++類中的物件方法。
userdata
lua中userdata為自定義型別,即使用者自定義c++類型別,非lua基本型別。繫結過程中用來存放c++類物件指標,從而將c++類對映到lua中。
元表(metatable)
帶有索引的集合的表,繫結過程中用來存放和對映c++類中的物件和物件方法。
__index
元表索引,指向用來存放userdata的元表。用來索引已建立的元表棧中的c++類名以及類方法名。
接下來完成實現部分,在 fun.cpp 中新增如下**:
#include**詳解:"fun.h"
extern
"c"// 1.
intl_foo_constructor
(lua_state *l
)// 2.
foo*
l_checkfoo
(lua_state *l
,intn)
// 3.
intl_foo_add
(lua_state *l
)// 4.
intl_foo_destructor
(lua_state *l
)// 5.
void
registerfoo
(lua_state *l
),,,
};lual_newmetatable(l
,"lual_foo"
);lual_register(l
,null
,sfooregs
);lua_setfield(l
,-1,
"__index"
);lua_setglobal(l
,"foo"
);}
1. c++繫結到lua的建構函式,lual_checkstring用來檢查建構函式的形參是否為string型別並返回這個string。利用lua_newuserdata建立乙個userdata來存放foo類物件指標。lual_getmetatable將與名為lual_foo相關聯的元表推入棧中。此時,lua棧中的內容如下:
3lua_setmetatable 將位於lua棧中-2位置的 userdata 新增到元表 lual_foo 中。最後,返回值1使得lua可以得到userdata,之後棧將會被清空。|metatable
"lual_foo"|-1
2|userdata |-2
1|string
parameter
|-3
2. lual_checkudata 用來檢測形參是否為 lual_foo 元表中的userdata,並返回這個userdata。
3. 此函式是將c++類中的add()函式對映到lua中, lua_pushstring 將字串壓入棧中,返回值1使得字串返回給lua呼叫函式。
4. 此函式是將c++類中的析構函式對映到lua中。
5. 此函式是註冊c++類到lua和註冊所有已繫結的c++函式到lua。 sfooregs 給每個已繫結的c++函式乙個能被lua訪問的名字。 lual_newmetatable 建立乙個名為lual_foo的元表並壓入棧定, lual_register 將 sfooregs 新增到lual_foo中。 lua_pushvalue 將lual_foo元表中元素的拷貝壓入棧中。 lua_setfield 將lual_foo元表的index域設為 __index 。 lua_setglobal 將元表lual_foo重新命名為foo並將它設為lua的全域性變數,這樣lua可以通過識別foo來訪問元表lual_foo,並使lua指令碼能夠覆蓋元表foo,即覆蓋c++函式。如此一來,使用者可以用lua**自定功能,覆蓋掉c++類中函式的功能,極大地提高了**靈活性。
現在新增繫結函式的函式宣告至 fun.h 中:
int新增如下**到 fun.lua :l_foo_constructor
(lua_state *l
);foo
*l_checkfoo
(lua_state *l
,intn);
intl_foo_add
(lua_state *l
);int
l_foo_destructor
(lua_state *l
);void
registerfoo
(lua_state *l
);
function1. 同名函式覆蓋繫結的c++函式,提高擴充套件性。foo:
speak
("hello, i am a foo"
)end
local
foo
=foo
.new
("fred"
)localm =
foo:
add(3,
4)print(m
)foo
:speak
()foo
.add_
=foo
.add
// 1.
function
foo:
add(a,
b)return
"here comes the magic: "
..self
:add_(a
,b)endm =
foo:
add(9,
8)print(m
)
// register lua engine注意: 因為cocos2d-x lua binding目前不支援多個狀態,所以在註冊已繫結的c++類時,只能使用當前執行的狀態。auto
engine
=luaengine
::getinstance
();scriptenginemanager
::getinstance
()->
setscriptengine
(engine
);// adding code here...
// register lua binding
registerfoo
(engine
->
getluastack
()->
getluastate
());
std::
string
path
=fileutils
::getinstance
()->
fullpathforfilename
("fun.lua"
);engine
->
executescriptfile
(path
.c_str
());
執行程式,如果得到下面的輸出結果證明已經繫結成功:
foo如果希望在android環境下除錯,在執行 proj.android/build_native 指令碼前,需要在 proj.android/jni/android.mk 檔案中新增 fun.cpp 檔案包含:isborn
cocos2d:[
lua-
]fred:3
+4=7
cocos2d:[
lua-
]hello
,i am a
foococos2d:[
lua-
]here comes the magic
:fred:9
+8=17
local_src_files:=hellolua
/main
.cpp \
../../
classes/.
cpp \
../../
classes
/fun
.cpp
Cocos2d x手動繫結C 類到Lua
最近開始學習cocos2d x中使用lua,而我的目標也只是顯示,部分邏輯,任務,劇情,新手引導使用lua,網路 資料等部分打算還是使用c 所以先看了看笨木頭介紹的簡單lua入門,在c 中呼叫lua函式,訪問lua的全域性變數以及表結構,在lua中呼叫c 函式。看完這些大概對lua的堆疊和訪問方式有...
cocos2d x 布景層類
cclayer是ccnode的子類,在此基礎上實現觸屏時間 協議。可以實現ccnode 類的功能,並且可以處理輸入,包括觸屏和加速度感測器。場景中可以有很多個布景層。繼承關係如下 cclayercolor是cclayer的子類,有兩個擴充套件功能 1 為布景層增添顏色。2 設定不透明度。cclaye...
整合quickx到普通cocos2dx
quickx是對cocos2dx的lua擴充套件,它做了一些c 的擴充套件,同時還在lua做了一些封裝,讓用lua開發cocos2dx更快,中文站 由於現在的專案對cocos2dx有一些修改,又想用到quickx的便捷,於是便想把quickx 整合到現在的專案裡。先從ccluastack開始逐漸修復...