Lua/C绑定,从lua绑定

Ske*_*een 0 c lua binding

我正在构建一个lua事件系统(在lua中),但是我希望能够从C中触发事件,我想将C函数绑定到lua函数,这样C函数可以在lua中触发事件,我打算用:

lua_register
Run Code Online (Sandbox Code Playgroud)

功能; 但是我似乎找不到像这样绑定我的lua函数的方法,看起来我需要一个lua函数来做同样的事情,但是从lua方面来说,我正在考虑做一些hack,将C函数绑定到lua,简单地调用'lua_register',但这对我来说似乎有些不安全.

那我该怎么做呢?

Nic*_*las 5

我不完全确定我理解你的要求.所以请允许我解释一下我认为你的问题是什么.

你有一些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只是一个便利功能,使它们相同.

你想要的是调用RegisterEventHandlerC代码,通过C函数作为第三个参数(记住:第一个参数是self,因为我叫RegisterEventHandler:替代的..如果您使用的是全球性的活动系统,而不是面向对象的一个,你只有两个参数).这需要两件事:

  1. 您必须知道如何从C代码调用Lua函数.
  2. 您必须知道如何将C函数传递给Lua代码.

第1步:这一切都是通过Lua堆栈完成的(我假设你知道它是如何工作的.如果没有,我有一个非常实质性的答案,解释了你可能想知道的大部分内容).

您需要做的第一件事是获取要调用堆栈的函数.为此,您需要获取一个事件系统对象(同样,如果您的事件系统是全局的,只需获取全局表)并将其推送到堆栈中.如何执行此操作取决于事件系统对象的存储位置.大概你可以通过全局表来获取它们.

一旦你在堆栈上有了事件系统,你只需用"RegisterEventHandler"字符串索引它,这将返回我们需要的Lua函数.

接下来,我们将参数从头到尾推送到堆栈.第一个参数是事件系统对象; 它可能仍然在堆栈上,所以我们可以复制它.第二个是事件名称,这很容易推动.第三是C函数.这导致我们:

第2步: lua_register不会完成工作.这太沉重了; 它将C函数放在全局表中.我们需要它在堆栈上.所以我们必须使用较低级别的功能:lua_pushcclosure.或者lua_pushcfunction,如果您不需要upvalues.

这些函数采用C函数,将其包装在Lua中,然后将其推送到Lua堆栈.

现在3个参数都在堆栈上,我们可以通过调用来调用事件注册函数lua_pcall.或者你最喜欢的Lua函数调用函数; 但是你希望这样做.Lua将消耗3个参数和函数本身,因此它们不再在堆栈中.

并且由于事件注册函数可能不返回值,因此堆栈将在我们将函数放入堆栈之前(但不是在我们开始之前,取决于在获取函数时完成了多少清理).

在此之后,您的C函数将注册到该事件名称的事件处理程序.