2011-09-17 94 views
0

我目前正在構建一個lua事件系統(在lua中),但是我希望能夠從C中觸發事件,我想將一個C函數綁定到一個lua函數,因此C函數可能觸發lua中的事件,我打算使用以下函數:Lua/C綁定,從lua綁定

lua_register 

函數;然而,我似乎無法找到一種方法來綁定我的lua函數,就像這樣,似乎我需要一個lua函數來做同樣的事情,但從lua方面來說,我正在考慮做一些破解,將一個C函數綁定到lua中,該函數簡單地稱爲'lua_register',但這對我來說似乎有點不安全。

那我該怎麼做呢?

回答

5

我不完全確定我明白你的要求。所以讓我解釋一下我認爲你的問題是什麼。

你有一些Lua代碼。在那個Lua代碼中,你有一個系統。這個系統在某個時候給了一個或多個事件。對於每個給定的事件,它會調用一些函數或函數,這些函數在給定特定事件時被註冊爲被調用。

因此,該系統具有兩個基本功能:

EventSystem:RegisterEventHandler(EventName, Func); 
EventSystem:FireEvent(EventName, ...); 

RegisterEventHandler方法給出Func與給定EventName聯繫起來,這樣當FireEvent稍後被調用,Func將被告知是否給予EventNameFireEventFunc是一樣的。

現在,您希望讓C代碼能夠將C函數註冊爲事件處理函數。所以現在是時候談論在Lua中註冊C函數了。

C API調用lua_register實際上是一個宏。它在Lua堆棧上創建一個C函數,然後使用給定的字符串索引將其放入全局表中。lua_register。這兩個是分開的操作; lua_register只是一個使它們相同的便利功能。

你想要的是調用RegisterEventHandler從C代碼,通過C函數作爲第三個參數(記住:第一個參數是self,因爲我叫RegisterEventHandler:而不是.如果您使用的是全球性的活動系統而不是一個面向對象的系統,你只有兩個參數)。這需要兩件事:

  1. 你必須知道如何從C代碼中調用Lua函數。
  2. 你必須知道如何將C函數傳遞給Lua代碼。

第1步:它通過的Lua棧全部完成(我假設你知道如何工作的如果不是這樣,我有一個pretty substantial answer that explains most everything you might want to know about it)。

您需要做的第一件事就是獲得您想要調用到堆棧上的函數。爲此,您需要獲取事件系統對象(如果您的事件系統是全局的,則只需獲取全局表)並將其推入堆棧。你怎麼做取決於你的事件系統對象的存儲位置。想必您可以通過全球表獲得他們。

一旦你在堆棧中有事件系統,你只需要使用"RegisterEventHandler"字符串索引它,它會返回我們需要的Lua函數。

接下來,我們將參數從第一個推到最後一個。第一個參數是事件系統對象;它可能仍然在堆棧中,所以我們可以複製它。第二個是事件名稱,這很容易推動。第三個是C函數。這導致我們:

第2步:lua_register是不會完成工作。這太過沉重;它將C函數放在全局表中。我們需要它在堆棧上。所以我們必須使用較低級別的功能:lua_pushcclosure。或者lua_pushcfunction,如果你不需要upvalues。

這些函數採用C函數,將其包裝在Lua中,並將其推入Lua堆棧。

現在3個參數在堆棧上,我們可以調用事件註冊函數lua_pcall。或者你最喜歡的Lua函數調用函數;但是你希望這樣做。 Lua將使用3個參數和函數本身,以便它們不再處於堆棧中。

而且由於事件註冊函數可能不會返回值,所以在我們將函數放入堆棧之前(但不是在開始之前),堆棧將處於正確的位置,具體取決於獲取功能)。

之後,你的C函數將被註冊到該事件名稱的事件處理程序中。

+0

我很抱歉讓你失望,但我實際上正在尋找的是從C調用'FireEvent'的方法,因爲我希望我的lua系統知道遊戲引擎狀態。 – Skeen

+0

@Skeen:那就叫它。按照我的建議,只使用不同的名稱和參數。當然,不要在Lua中創建C函數。只需在Lua堆棧中調用你想調用的函數,然後將你想要使用的參數放在堆棧上,然後調用該函數即可。 –

+0

很明顯啊! - 謝謝! – Skeen