Suche…


Syntax

  • lua_State * L = lua_open (); // einen neuen VM-Status erstellen; Lua 5,0
  • lua_State * L = luaL_newstate (); // einen neuen VM-Status erstellen; Lua 5.1+
  • int luaL_dofile (lua_State * L, const char * Dateiname ); // Lua-Skript mit dem angegebenen Dateinamen unter Verwendung des angegebenen lua_State ausführen
  • void luaL_openlibs (lua_State * L); // Lade alle Standardbibliotheken in den angegebenen lua_State
  • void lua_close (lua_State * L); // Schließen Sie den VM-Status und geben Sie alle Ressourcen frei
  • void lua_call (lua_State * L, int nargs, int nresults); // Aufruf des luavalue unter index - (nargs + 1)

Bemerkungen

Lua bietet auch eine geeignete C-API für die virtuelle Maschine. Im Gegensatz zu VM selbst ist die C-API-Schnittstelle stapelbasiert. Die meisten Funktionen, die mit Daten verwendet werden sollen, sind das Hinzufügen von Daten auf dem virtuellen Stapel oder das Entfernen von Daten. Außerdem müssen alle API-Aufrufe innerhalb des Stapels und seinen Einschränkungen sorgfältig verwendet werden.

Im Allgemeinen kann alles, was in der Lua-Sprache verfügbar ist, mithilfe der C-API ausgeführt werden. Darüber hinaus gibt es einige zusätzliche Funktionen wie direkten Zugriff auf die interne Registrierung, Änderungsverhalten des Standardspeicherzuordners oder Garbage Collector.

Sie können bereitgestellte Lua C-API-Beispiele kompilieren, indem Sie Folgendes auf Ihrem Terminal ausführen:

$ gcc -Wall ./example.c -llua -ldl -lm

Lua Virtual Machine erstellen

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

int main(void)
{
5.1
  /* Start by creating a new VM state */
  lua_State *L = luaL_newstate();

  /* Load standard Lua libraries: */
  luaL_openlibs(L);
5.1
  /* For older version of Lua use lua_open instead */
  lua_State *L = lua_open();

  /* Load standard libraries*/
  luaopen_base(L);
  luaopen_io(L);
  luaopen_math(L);
  luaopen_string(L);
  luaopen_table(L);
    /* do stuff with Lua VM. In this case just load and execute a file: */
    luaL_dofile(L, "some_input_file.lua");

    /* done? Close it then and exit. */
    lua_close(L);

    return EXIT_SUCCESS;
}

Lua-Funktionen aufrufen

#include <stdlib.h>

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int main(void)
{
    lua_State *lvm_hnd = lua_open();
    luaL_openlibs(lvm_hnd);

    /* Load a standard Lua function from global table: */
    lua_getglobal(lvm_hnd, "print");

    /* Push an argument onto Lua C API stack: */
    lua_pushstring(lvm_hnd, "Hello C API!");

    /* Call Lua function with 1 argument and 0 results: */
    lua_call(lvm_hnd, 1, 0);

    lua_close(lvm_hnd);

    return EXIT_SUCCESS;
 }

Im obigen Beispiel machen wir diese Dinge:

  • Erstellen und Einrichten von Lua VM wie im ersten Beispiel gezeigt
  • Lua-Funktion vom globalen Lua-Tisch auf den virtuellen Stack holen und verschieben
  • String "Hello C API" als Eingabeargument auf den virtuellen Stack schieben
  • VM anweisen, eine Funktion mit einem Argument aufzurufen, das sich bereits im Stack befindet
  • schließen und aufräumen

HINWEIS:

lua_call() , dass lua_call() die Funktion und ihre Argumente aus dem Stack lua_call() und nur das Ergebnis lua_call() .

Es wäre auch sicherer, stattdessen einen Lua-geschützten Aufruf zu verwenden - lua_pcall() .

Integrierter Lua-Interpreter mit benutzerdefinierter API und Lua-Anpassung

Demonstrieren Sie, wie Sie einen Lua-Interpreter in C-Code einbetten, eine C-definierte Funktion für das Lua-Skript verfügbar machen, ein Lua-Skript auswerten, eine C-definierte Funktion von Lua aufrufen und eine Lua-definierte Funktion von C (dem Host) aufrufen.

In diesem Beispiel möchten wir, dass die Stimmung durch ein Lua-Skript festgelegt wird. Hier ist mood.lua:

-- Get version information from host
major, minor, build = hostgetversion()
print( "The host version is ", major, minor, build)
print("The Lua interpreter version is ", _VERSION)

-- Define a function for host to call
function mood( b )

    -- return a mood conditional on parameter
    if (b and major > 0) then
        return 'mood-happy'
    elseif (major == 0) then
        return 'mood-confused'
    else
        return 'mood-sad'
    end
end

Beachten Sie, dass mood() nicht im Skript aufgerufen wird. Es ist nur für die Hostanwendung definiert, die aufgerufen werden soll. hostgetversion() auch, dass das Skript eine Funktion namens hostgetversion() , die nicht im Skript definiert ist.

Als Nächstes definieren wir eine Hostanwendung, die 'mood.lua' verwendet. Hier ist die 'hostlua.c':

#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

/* 
 * define a function that returns version information to lua scripts
 */
static int hostgetversion(lua_State *l)
{
    /* Push the return values */
    lua_pushnumber(l, 0);
    lua_pushnumber(l, 99);
    lua_pushnumber(l, 32);

    /* Return the count of return values */
    return 3;
}

int main (void)
{
    lua_State *l = luaL_newstate();
    luaL_openlibs(l);

    /* register host API for script */
    lua_register(l, "hostgetversion", hostgetversion);

    /* load script */
    luaL_dofile(l, "mood.lua");

    /* call mood() provided by script */
    lua_getglobal(l, "mood");
    lua_pushboolean(l, 1);
    lua_call(l, 1, 1);

    /* print the mood */
    printf("The mood is %s\n", lua_tostring(l, -1));
    lua_pop(l, 1);

    lua_close(l);
    return 0;
}

Und hier ist die Ausgabe:

The host version is     0    99    32
Lua interpreter version is     Lua 5.2
The mood is mood-confused

Auch nachdem wir 'hostlua.c' kompiliert haben, können Sie 'mood.lua' noch ändern, um die Ausgabe unseres Programms zu ändern!

Tabellenmanipulation

Um auf einen Index für eine Tabelle zuzugreifen oder ihn zu ändern, müssen Sie die Tabelle irgendwie in den Stapel legen.
Nehmen wir für diese Beispiele an, dass Ihre Tabelle eine globale Variable mit dem Namen tbl ist.

Den Inhalt an einem bestimmten Index abrufen:

int getkey_index(lua_State *L)
{
  lua_getglobal(L, "tbl");    // this put the table in the stack
  lua_pushstring(L, "index"); // push the key to access
  lua_gettable(L, -2);        // retrieve the corresponding value; eg. tbl["index"]

  return 1;                   // return value to caller
}

Wie wir gesehen haben, müssen Sie lediglich den Tisch in den Stapel schieben, den Index nach oben drücken und lua_gettable aufrufen. Das Argument -2 bedeutet, dass die Tabelle das zweite Element von oben im Stapel ist.
lua_gettable löst Metamethoden aus. Wenn Sie keine Metamethods auslösen möchten, verwenden Sie stattdessen lua_rawget. Es verwendet die gleichen Argumente.

Festlegen des Inhalts an einem bestimmten Index:

int setkey_index(lua_State *L)
{
  // setup the stack
  lua_getglobal(L, "tbl");
  lua_pushstring(L, "index");
  lua_pushstring(L, "value");
  // finally assign the value to table; eg. tbl.index = "value"
  lua_settable(L, -3);

  return 0;
}

Die gleiche Übung wie beim Abrufen des Inhalts. Sie müssen den Stapel schieben, den Index schieben und dann den Wert in den Stapel schieben. Danach rufen Sie lua_settable auf. Das Argument -3 ist die Position der Tabelle im Stapel. Um zu vermeiden, dass Metamethoden ausgelöst werden, verwenden Sie lua_rawset anstelle von lua_settable. Es verwendet die gleichen Argumente.

Übertragen des Inhalts von einer Tabelle in eine andere:

int copy_tableindex(lua_State *L)
{
    lua_getglobal(L, "tbl1"); // (tbl1)
    lua_getglobal(L, "tbl2");// (tbl1)(tbl2)
    lua_pushstring(L, "index1");// (tbl1)(tbl2)("index1")
    lua_gettable(L, -3);// (tbl1)(tbl2)(tbl1.index1)
    lua_pushstring(L, "index2");// (tbl1)(tbl2)(tbl1.index1)("index2")
    lua_pushvalue(L, -2); // (tbl1)(tbl2)(tbl1.index1)("index2")(tbl1.index1)
    lua_settable(L, -4);// (tbl1)(tbl2)(tbl1.index1)
    lua_pop(L, 1);

    return 0;
}

Jetzt stellen wir alles zusammen, was wir hier gelernt haben. Ich stelle den Stack-Inhalt in die Kommentare, damit Sie nicht verloren gehen.

Wir legen beide Tabellen in den Stapel, schieben den Index von Tabelle 1 in den Stapel und erhalten den Wert bei tbl1.index1 . Beachten Sie das -3 Argument für "erreichbar". Ich schaue auf den ersten Tisch (dritten von oben) und nicht auf den zweiten. Dann verschieben wir den Index der zweiten Tabelle, kopieren die tbl1.index1 an den Anfang des Stapels und rufen dann lua_settable für das vierte Element von oben auf.

Zum Hausputz habe ich das oberste Element gesäubert, sodass nur die beiden Tische am Stapel bleiben.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow