Speichern der Referenz auf die Lua-Funktion in C

7

Ich habe einen einfachen Event-Handler in C ++ implementiert. Ich habe auch einen eingebetteten Lua-Interpreter in meiner Anwendung, den ich mit dem Event Manager interagieren muss. Das ultimative Ziel besteht darin, einen Ereignishandler zu haben, der sowohl c ++ - als auch Lua-Funktionen ausführt, wenn ein Ereignis ausgelöst wird.

Mein Problem ist, dass ich keine einfache Möglichkeit finde, Verweise auf die Lua-Funktionen in meinem C ++ - Code zu speichern. Ich weiß, wie man Lua-Funktionen von c ausführt (mit lua_getglobal und lua_pcall ), aber ich würde lieber einen Verweis auf die Funktion selbst speichern, so dass ich eine Lua-Funktion direkt an registerListener

übergeben kann

Hinweis Es kann davon ausgegangen werden, dass die Benutzerdaten für alle Lua-Listener NULL sind.

Hier ist mein Code:

EventManager.h

%Vor%

EventManager.cpp

%Vor%

luaw_eventmanager.h

%Vor%

luaw_eventmanager.cpp

%Vor%     
ewok 10.10.2012, 16:16
quelle

3 Antworten

6

Ich würde vorschlagen, Ihre Funktionen in der -Registrierung zu speichern und den Referenzmechanismus zu verwenden, der von den Funktionen luaL_ref und luaL_unref bereitgestellt wird.

Diese Funktionen verwenden einen C int -Wert, um auf die Werte zuzugreifen. Es ist einfach, einen solchen ganzzahligen Wert beispielsweise in einem C ++ - Klassenelement zu speichern.

    
prapin 10.10.2012, 17:31
quelle
14

Alle Lua-eigenen Objekte werden von Müll gesammelt. Dies beinhaltet Funktionen. Selbst wenn Sie also einen Verweis auf eine Lua-Funktion erhalten könnten, wäre Lua immer noch Eigentümer und würde daher dem GC unterliegen, wenn Lua erkennt, dass es nicht mehr referenziert wird.

>

Externer Code kann keine Lua-Referenz besitzen. Aber externer Code kann diese Referenz an einem Ort speichern, den der Lua-Code nicht erreichen kann (und daher nicht brechen kann): die Lua-Registrierung.

Die Lua-Registry ist eine Lua-Tabelle (die sich im Stack-Pseudo-Index% co_de befindet %, also vom Stack aus zugänglich), auf den Lua-Code nicht (direkt) zugreifen kann. Daher ist es ein sicherer Ort für Sie, was Sie benötigen. Da es sich um eine Lua-Tabelle handelt, können Sie sie wie jede andere Lua-Tabelle manipulieren (indem Sie Werte, Schlüssel usw. hinzufügen).

Die Registrierung ist jedoch global, und wenn Sie andere C-Module verwenden, ist es durchaus möglich, dass sie sich gegenseitig anstampfen. Es ist also eine gute Idee, einen spezifischen Registrierungsschlüssel für jedes Modul auszuwählen und eine Tabelle innerhalb dieses Registrierungsschlüssels zu erstellen.

Schritt eins: Wenn Sie Ihren C-Schnittstellencode initialisieren, erstellen Sie eine Tabelle und stecken Sie sie in einen bekannten Schlüssel in der Registrierungstabelle. Nur ein leerer Tisch.

Wenn der Lua-Code eine Lua-Funktion als Callback übergibt, lade diese Tabelle aus dem speziellen Schlüssel und halte die Lua-Funktion dort. Natürlich müssen Sie jeder registrierten Funktion einen eindeutigen Schlüssel geben (den Sie als LUA_REGISTRYINDEX data der Lua-Funktion speichern), den Sie später zum Abrufen dieser Funktion verwenden können.

Lua hat einen einfachen Mechanismus dafür: void* . Diese Funktion registriert das Objekt oben auf dem Stapel mit der Tabelle, die es erhält. Dieser Registrierungsprozess gibt garantiert eindeutige Integer-Schlüssel für jedes registrierte Objekt zurück (solange Sie nicht manuell die Tabelle hinter der Rückseite des Systems ändern). luaL_ref gibt eine Referenz frei, allo

Da es sich bei den Referenzen um ganzzahlige Schlüssel handelt, könnten Sie einfach einen Cast von luaL_unref bis int durchführen und dies wären die Daten. Ich würde wahrscheinlich ein explizites Objekt verwenden ( void* ing an malloc ), aber Sie können es beliebig speichern.

Schritt zwei: Wenn eine Lua-Funktion registriert ist, verwenden Sie int , um sie der in Schritt 1 erstellten Registrierungstabelle hinzuzufügen. Speichern Sie den von dieser Funktion zurückgegebenen Schlüssel im Parameter luaL_ref die registrierte Funktion.

Schritt drei: Wenn diese Funktion aufgerufen werden muss, verwenden Sie den Integer-Schlüssel, den Sie im Parameter void* gespeichert haben, um auf die in Schritt 1 erstellte Registrierungstabelle zuzugreifen. Dadurch erhalten Sie die Funktion die Sie dann mit den üblichen Lua-Methoden aufrufen können.

Schritt vier: Wenn Sie die Lua-Funktion abmelden, verwenden Sie void* , um die Funktion freizugeben (dadurch vermeiden Sie, dass Luas Speicher ausgelaufen wird). Wenn Sie% ed_de% ed Speicher zum Speichern des Integer-Schlüssels verwenden, luaL_unref hier.

    
Nicol Bolas 10.10.2012 17:41
quelle
2

@Nicolas Bolas hat nette Anweisungen gegeben, aber sind zu vage für Neulinge (einschließlich mir selbst). Durch Versuch und Irrtum habe ich ein funktionierendes Beispiel gefunden:

Speicher

%Vor%

Abrufen

%Vor%     
Mikel 11.08.2015 21:12
quelle

Tags und Links