轉(zhuǎn)載自:(http://www.cnblogs.com/flyFreeZn/p/4152881.html)
相信很多朋友在使用cocos2d-x+lua開發(fā)游戲時(shí)都遇到過接入iOS原生SDK的問題报嵌,比如常見的接應(yīng)用內(nèi)支付SDK少孝,廣告SDK或是一些社交平臺(tái)SDK等等,我也沒少接過這類SDK挥转。這篇文章主要是對(duì)我做過項(xiàng)目中接入iOS原生SDK實(shí)現(xiàn)方案的一個(gè)總結(jié),在這里分享給大家世落,希望對(duì)自己和大家的開發(fā)工作都有幫助郎笆。
在展開正文之前,先做幾點(diǎn)說明:
1.我這里說的iOS原生SDK是指那些完全用Objective-C語言開發(fā)监婶,為原生iOS程序設(shè)計(jì)的SDK旅赢。swift很好很強(qiáng)大齿桃,不過我還沒用過,慚愧煮盼,不過語言終歸只是表達(dá)方式而已短纵,解決問題的思路都是一樣的;
2.這里假設(shè)游戲的主要邏輯使用lua實(shí)現(xiàn)僵控,對(duì)于主要邏輯使用C++實(shí)現(xiàn)的香到,用本文的思路一樣可行,并且設(shè)計(jì)上更簡單报破,接著往下看就知道了:)
3.本文以quick-cocos2d-x 2.1版本為例進(jìn)行講解悠就,主要因?yàn)檫@個(gè)是我之前做項(xiàng)目用得最多的一個(gè)版本,-x新版本變動(dòng)比較大充易,但是理卑,還是那句話,解決問題的思路是相同的蔽氨。
-------------------正式開始的分割線-------------------
好了藐唠,我們正式開始。開門見山鹉究!
**解決這種接入問題宇立,實(shí)際上最主要是解決不同語言交互的問題,一旦跨過語言交互的障礙自赔,剩下的事情就so easy!**
由于涉及到Lua,C++,Objective-C三種語言妈嘹,這個(gè)問題表面上看起來錯(cuò)綜復(fù)雜,但其實(shí)只要冷靜地(=绍妨。=)梳理润脸,我們便可以得到正確的思路。
因?yàn)槲覀冇螒虻倪壿嬛饕怯肔ua實(shí)現(xiàn)的(前面已經(jīng)做過假設(shè))他去,而SDK是用Objective-C實(shí)現(xiàn)毙驯,所以這里我們需要解決Lua與Objective-C的交互問題,即最終希望達(dá)到的目標(biāo)是灾测,在Lua層面“調(diào)用”O(jiān)bjective-C的代碼(注意這里的調(diào)用是加引號(hào)的爆价,間接的調(diào)用),而當(dāng)Objective-C層面收到SDK的回調(diào)媳搪,再通知Lua铭段。我們知道,Lua并沒有簡單的方法直接和Objective-C交流秦爆,但是Lua可以通過Lua Binding和C/C++交流序愚,而我們又知道,C++和Objective-C可以混編等限,即C++可以直接調(diào)用(這里調(diào)用沒引號(hào)爸吮,是真的直接調(diào)用)Objective-C的代碼芬膝。想到這里,思路就很明顯了拗胜,我們可以使用C++為Lua和Objective-C的交互充當(dāng)橋梁,進(jìn)而實(shí)現(xiàn)Lua到Objective-C的交互怒允。
根據(jù)上面的分析埂软,我們可以用如下圖表達(dá)我們的思路,我們這里將語言交互的過程分成了4個(gè)小部分:
**整個(gè)語言交互的過程可以總結(jié)為:Lua調(diào)用Lua Binding的C++接口纫事,C++接口調(diào)用混編的Objective-C接口勘畔,而Objective-C通過block形式的回調(diào),將結(jié)果通知給C++丽惶,C++通過Lua的C API將最終結(jié)果返回給Lua炫七。**這樣一趟下來,就完成了Lua與Objective-C的整個(gè)交互過程钾唬。
簡單的說一下這4部分:
1.Lua Binding
將C/C++接口導(dǎo)出給Lua調(diào)用的方法万哪,由于篇幅的原因這里就不展開了,具體可以參考Lua的文檔抡秆,以及網(wǎng)上其他地方的文章奕巍。
2.混編
Objective-C的一大優(yōu)點(diǎn)就是可以和C與C++混編使用,就像同一個(gè)語言一樣共存在一個(gè)實(shí)現(xiàn)文件里面儒士。具體混編規(guī)則也不說了的止,這里只提兩個(gè)小細(xì)節(jié):
一,在XCode下混編的實(shí)現(xiàn)文件后綴是.mm着撩,而不能是.cpp或者是.m诅福;
二,混編的實(shí)現(xiàn)文件引用頭文件的地方拖叙,C++或者C的用#include氓润,而Objective-C用#import,相互沒有影響薯鳍。
3.Block回調(diào)
Block是Objective-C一個(gè)非常棒的特性旺芽,更棒的是在Block里面還可以直接寫C++代碼:)具體想了解的可以看[蘋果官方文檔]
其實(shí)在最初,我曾經(jīng)嘗試過使用發(fā)送通知的方式來實(shí)現(xiàn)Objective-C對(duì)C++的回調(diào)辐啄,即Objective-C收到SDK回調(diào)采章,給C++部分發(fā)送附帶回調(diào)信息的通知,雖然cocos2d-x中有現(xiàn)成的NotificationCenter來幫助實(shí)現(xiàn)壶辜,但這種方式的一個(gè)顯而易見的弊端是大大增加了C++代碼和Objective-C代碼的耦合度悯舟,Objective-C部分也要混編C++調(diào)用C++的NotificationCenter發(fā)通知,C++部分也要混編Objective-C代碼砸民,調(diào)用C++的NotificationCenter收通知抵怎,這種結(jié)構(gòu)實(shí)在是有夠煩躁的奋救。
相比之下,使用Block回調(diào)就干凈利落太多反惕,Objective-C這邊一切都是純粹的尝艘,它并不需要知道自己要被C++調(diào)用還是Objective-C調(diào)用,也不需要花很多精力在返回回調(diào)上姿染,只需要干好自己的本職工作背亥,然后在適當(dāng)?shù)臅r(shí)候調(diào)用Block就一切搞定。
4.Lua C API
Lua C API用于C/C++與Lua的交互悬赏,在cocos2d-x中這些C API已經(jīng)被封裝成了更加易用的C++ Class API狡汉。這里要提到的是,在用這套API調(diào)用Lua函數(shù)的時(shí)候闽颇,為了傳參盾戴,需要參數(shù)入棧的操作,這個(gè)入棧的順序影響到了Lua函數(shù)接受到參數(shù)的順序兵多,不過好在規(guī)則很簡單:**先入棧的參數(shù)排在前**或者說是**入棧順序和實(shí)參順序相同**尖啡。舉例,如果C++這邊調(diào)用Lua函數(shù)func時(shí)剩膘,入棧的順序是A可婶,B,C援雇,那么就是調(diào)用函數(shù)func(A,B,C)
-------------------漸入佳境的分割線-------------------
在整個(gè)語言交互的過程中矛渴,如果認(rèn)為Lua是頂層,Objective-C是底層惫搏,那么在實(shí)際游戲中交互的過程就是一個(gè)自頂向下的過程具温,然而我們?cè)趯?shí)現(xiàn)各層級(jí)代碼的時(shí)候,需要自底向上完成筐赔,因?yàn)樵陧攲覮ua代碼中的邏輯铣猩,是由底層Objective-C SDK的接口與功能決定的。即**我們需要先根據(jù)SDK中原始的Objective-C的接口茴丰,做適合我們游戲Objective-C封裝代理類达皿,然后根據(jù)封裝結(jié)果實(shí)現(xiàn)C++的bridge接口,最后再實(shí)現(xiàn)Lua的對(duì)應(yīng)邏輯**贿肩。
根據(jù)以上分析峦椰,從層級(jí)的角度,設(shè)計(jì)如下:
除過Lua的邏輯汰规,我們最重要需要實(shí)現(xiàn)的兩部分內(nèi)容:C++ Bridge Class 和 Objective-C SDK Delegate Class汤功。前者是起橋梁作用的接口類,原則上不做任何與游戲邏輯相關(guān)的數(shù)據(jù)處理溜哮,而后者負(fù)責(zé)封裝原始的SDK接口滔金,接收以及初步處理SDK回調(diào)數(shù)據(jù)色解。前者的實(shí)現(xiàn)依賴于后者的實(shí)現(xiàn),而后者的實(shí)現(xiàn)又依賴于SDK餐茵。SDK取得的數(shù)據(jù)最終通過層層傳遞科阎,交給Lua邏輯處理,最終保證對(duì)數(shù)據(jù)處理的游戲邏輯盡可能多的放到Lua層中忿族。
這樣設(shè)計(jì)的好處有很多锣笨,一方面,頂層的游戲邏輯變動(dòng)肠阱,不影響下層多語言交互代碼票唆,另一方面朴读,底層的SDK變動(dòng)屹徘,如版本更新甚至更換,不影響上層游戲邏輯衅金,多層次結(jié)構(gòu)有效地降低了復(fù)雜度噪伊,隔離了變化,對(duì)于頻繁的需求變更氮唯,這種結(jié)構(gòu)也可以保證擴(kuò)展的便利鉴吹。
-------------------總結(jié)的分割線-------------------
綜上所述,解決接入iOS原生SDK的問題惩琉,主要需要4步:
1.根據(jù)SDK接口與功能實(shí)現(xiàn)Objective-C SDK Delegate Class豆励;
2.根據(jù)Objective-C SDK Delegate Class實(shí)現(xiàn)對(duì)應(yīng)的C++ Bridge Class;
3.根據(jù)C++ Bridge Class生成對(duì)應(yīng)的Lua Binding代碼瞒渠;
4.寫Lua層邏輯良蒸。