我正在构建一个lua事件系统(在lua中),但是我希望能够从C中触发事件,我想将C函数绑定到lua函数,这样C函数可以在lua中触发事件,我打算用:
lua_register
Run Code Online (Sandbox Code Playgroud)
功能; 但是我似乎找不到像这样绑定我的lua函数的方法,看起来我需要一个lua函数来做同样的事情,但是从lua方面来说,我正在考虑做一些hack,将C函数绑定到lua,简单地调用'lua_register',但这对我来说似乎有些不安全.
那我该怎么做呢?
我不完全确定我理解你的要求.所以请允许我解释一下我认为你的问题是什么.
你有一些Lua代码.在那个Lua代码中,你有一个系统.在某个时刻,该系统被给予一个或多个事件.对于给定的每个事件,它调用一些在给定特定事件时注册要调用的函数.
因此,该系统有两个基本功能:
EventSystem:RegisterEventHandler(EventName, Func);
EventSystem:FireEvent(EventName, ...);
Run Code Online (Sandbox Code Playgroud)
该RegisterEventHandler
方法将给定Func
与给定相关联EventName
,以便FireEvent
稍后Func
调用时,如果EventName
给定的FireEvent
是与Func
注册的相同,则将被调用.
现在,您希望C代码能够将C函数注册为事件处理程序.所以是时候讨论在Lua中注册C函数了.
C API调用lua_register
实际上是一个宏.它在Lua堆栈上创建一个C函数,然后使用给定的字符串索引将其放入全局表中lua_register
.这是两个独立的操作; lua_register
只是一个便利功能,使它们相同.
你想要的是调用RegisterEventHandler
C代码,通过C函数作为第三个参数(记住:第一个参数是self
,因为我叫RegisterEventHandler
用:
替代的.
.如果您使用的是全球性的活动系统,而不是面向对象的一个,你只有两个参数).这需要两件事:
第1步:这一切都是通过Lua堆栈完成的(我假设你知道它是如何工作的.如果没有,我有一个非常实质性的答案,解释了你可能想知道的大部分内容).
您需要做的第一件事是获取要调用堆栈的函数.为此,您需要获取一个事件系统对象(同样,如果您的事件系统是全局的,只需获取全局表)并将其推送到堆栈中.如何执行此操作取决于事件系统对象的存储位置.大概你可以通过全局表来获取它们.
一旦你在堆栈上有了事件系统,你只需用"RegisterEventHandler"
字符串索引它,这将返回我们需要的Lua函数.
接下来,我们将参数从头到尾推送到堆栈.第一个参数是事件系统对象; 它可能仍然在堆栈上,所以我们可以复制它.第二个是事件名称,这很容易推动.第三是C函数.这导致我们:
第2步: lua_register
不会完成工作.这太沉重了; 它将C函数放在全局表中.我们需要它在堆栈上.所以我们必须使用较低级别的功能:lua_pushcclosure
.或者lua_pushcfunction
,如果您不需要upvalues.
这些函数采用C函数,将其包装在Lua中,然后将其推送到Lua堆栈.
现在3个参数都在堆栈上,我们可以通过调用来调用事件注册函数lua_pcall
.或者你最喜欢的Lua函数调用函数; 但是你希望这样做.Lua将消耗3个参数和函数本身,因此它们不再在堆栈中.
并且由于事件注册函数可能不返回值,因此堆栈将在我们将函数放入堆栈之前(但不是在我们开始之前,取决于在获取函数时完成了多少清理).
在此之后,您的C函数将注册到该事件名称的事件处理程序.