Cocos2d x手動繫結C 類到Lua

2021-06-21 09:09:30 字數 4618 閱讀 2915

cocos2d-x 3.0開始, lua binding使用tolua++方式自動繫結底層c++類到lua層,使使用者能夠用lua方式呼叫引擎各種介面。但是使用者還是希望手動繫結某些自定義類,所以接下來的內容將一步一步講解如何手動將自定義c++類繫結到lua。

首先,定義乙個類foo,這個類就是接下來要繫結到lua的類。

注意:所有c++類檔案必須放在 classes 資料夾裡,所有lua檔案必須放在 resources 資料夾裡。

在 fun.h 標頭檔案中新增如下**:

#include

#include

class

foostd

::string

add(

inta

,intb)

~foo

()private

:std

::string

name

;};

這個類有三個函式,建構函式、add函式和析構函式。作用是輸出不同字串,以判斷各函式是否被呼叫。

開始前,先了解下繫結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棧中的內容如下:

3

|metatable

"lual_foo"|-1

2|userdata |-2

1|string

parameter

|-3

lua_setmetatable 將位於lua棧中-2位置的 userdata 新增到元表 lual_foo 中。最後,返回值1使得lua可以得到userdata,之後棧將會被清空。

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

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

);

新增如下**到 fun.lua :

function

foo:

speak

()print

("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

)

1. 同名函式覆蓋繫結的c++函式,提高擴充套件性。

// register lua engine

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

());

注意: 因為cocos2d-x lua binding目前不支援多個狀態,所以在註冊已繫結的c++類時,只能使用當前執行的狀態。

執行程式,如果得到下面的輸出結果證明已經繫結成功:

foo

isborn

cocos2d:[

lua-

print

]fred:3

+4=7

cocos2d:[

lua-

print

]hello

,i am a

foococos2d:[

lua-

print

]here comes the magic

:fred:9

+8=17

如果希望在android環境下除錯,在執行 proj.android/build_native 指令碼前,需要在 proj.android/jni/android.mk 檔案中新增 fun.cpp 檔案包含:

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開始逐漸修復...