加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

将Go函数导入Lua中供lua调用

发布时间:2020-12-14 22:04:18 所属栏目:大数据 来源:网络整理
导读:有一个需求,就是使用go语言来实现一些基本模块,使用lua来实现基本逻辑,于是就有了在lua中调用go函数的需求。 go的资料非常少,好在go可以嵌入c语言,使得这个实现变得有可行性。 最终使用了lua中的full userdata来实现这个东西。将go中的函数全部封装成us

有一个需求,就是使用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() {
	//	初始化导出map
	C.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代码中进行注册。

//	压入gofunction
func (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 valid
		int* pUserData = (int*)luaL_checkudata(L,g_szGoMetaTable);
		if(0 != pUserData)
		{
			int nGoFunctionSeq = *pUserData;

			// get the golua_state
			void* pLuaGoState = luago_getGoLuaState(L);
			//	call go callback
			return (int)luago_call(pLuaGoState,nGoFunctionSeq);
		}
		else
		{
			luaL_argcheck(L,pUserData != 0,"GoFunction expected");
		}
	}
	
	luago_error(L,"trying to call a non-callable object");
	return 0;
}
这个也很简单,将userdata的序列取出,调用go的回调函数,在go中通过这个序列找出对应的函数,调用这个函数即可。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读