將Go函數匯入Lua中供lua調用

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

有一個需求,就是使用go語言來實現一些基本模組,使用lua來實現基本邏輯,於是就有了在lua中調用go函數的需求。

go的資料非常少,好在go可以嵌入c語言,使得這個實現變得有可行性。

最終使用了lua中的full userdata來實現這個東西。將go中的函數全部封裝成userdata,供lua調用。這樣是可行的,由於userdata可以設定metatable,metatable內可以設定一個原方法__call,那麼如下的調用:func(1, 3) 就可以變成func.metatable.__call(func, 1, 3),我們只要在c中實現這麼一個元方法,裝入特定的metatable中,將此metatable設為函數userdata的metatable,那麼就可以實現這個需求了。

在lua指令碼中的所有調用,均會調用到go中的c代碼部分,在c函數中,將此userdata解析,確定到某個go函數,那麼在go中再調用go語言部分,那麼lua-》go的橋樑就已經打通了。


那麼,我們可以在go中定義一個結構

type LuaGo_State struct {    ....BasePart    gofunctions map[int]interface{}    baseSeq int}

在BasePart中應該已經實現了lua的一些基本操作,比如建立什麼的,我就不貼了。baseSeq是匯出的gofunction的序號,用於回調時確定回調的go函數。gofunctions則記錄著某個序號對應的gofunction。

然後,我們需要在lua_state中記錄該lua_state中對應的LuaGo_State。

//開啟gofunction註冊支援func (this *LuaGo_State) LuaGo_OpenInvokeCompenent() {//初始化匯出mapC.luago_open(this.handle, unsafe.Pointer(this))this.gofunctions = make(map[int]interface{})this.baseSeq = 1}
於是我們要在c代碼中壓入LuaGo_State。


接下來就是註冊某個Go函數了,每個go函數對應一個LuaGo_State裡面的序列,然後在map中做下記錄,最後在c代碼中進行註冊。

//壓入gofunctionfunc (this *LuaGo_State) LuaGo_PushGoFunction(_name string, _func LuaGo_Function) int {funcSeq := this.luago_getGoFunctionSeq()this.gofunctions[funcSeq] = _func//註冊到lua中cfuncname := C.CString(_name)C.luago_pushGoFunction(this.handle, cfuncname, C.int(funcSeq))C.free(unsafe.Pointer(cfuncname))return funcSeq}

在c代碼中,思路就是為這個go函數建立一個userdata,userdata的值就是它的序號,然後設定好上述的metatable,記錄在lua_state的全域變數裡。那麼在lua中進行函數調用時候,就會調用我們c中的原方法。


//元方法static int luago_metamethod_call(struct lua_State* L){//stack userdata, parameters...if(lua_isuserdata(L, 1)){//check validint* pUserData = (int*)luaL_checkudata(L, 1, g_szGoMetaTable);if(0 != pUserData){int nGoFunctionSeq = *pUserData;// get the golua_statevoid* pLuaGoState = luago_getGoLuaState(L);//call go callbackreturn (int)luago_call(pLuaGoState, nGoFunctionSeq);}else{luaL_argcheck(L, pUserData != 0, 1, "GoFunction expected");}}luago_error(L, "trying to call a non-callable object");return 0;}
這個也很簡單,將userdata的序列取出,調用go的回呼函數,在go中通過這個序列找出對應的函數,調用這個函數即可。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.