Różnice między wybraną wersją a wersją aktualną.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
c_i_lua [2010/12/28 19:44] sjablon1 |
c_i_lua [2010/12/29 12:22] (aktualna) sjablon1 |
||
|---|---|---|---|
| Linia 88: | Linia 88: | ||
| === Instrukcje i funkcje === | === Instrukcje i funkcje === | ||
| + | Lua posiada standardowe instrukcje znane z języków Pascal/C: | ||
| + | |||
| + | * instrukcja przypisania =; | ||
| + | * instrukcje warunkowe, if/elseif/else/end; | ||
| + | * pętle, for/do/end, while,do,end, repeat/until; | ||
| + | * wywołanie funkcji; | ||
| + | * lokalna deklaracja zmiennych; | ||
| - | Instrukcje i funkcje | ||
| - | Lua obsługuje standardowy zestaw instrukcji | ||
| - | podobnych do tych stosowanych w języku | ||
| - | Pascal czy C. Istnieje możliwość definiowania | ||
| - | bloków instrukcji objętych słowami kluczowymi | ||
| - | do i end, które można kontrolować | ||
| - | poprzez break czy return. Na listę pojedynczych | ||
| - | instrukcji składają się: | ||
| - | • instrukcje przypisania =; | ||
| - | • instrukcje warunkowe, if/elseif/else/ | ||
| - | end; | ||
| - | • pętle, for/do/end, while/do/end, repeat/ | ||
| - | until/; | ||
| - | • wywołania funkcji; | ||
| - | • lokalne deklaracje zmiennych. | ||
| - | Instrukcja przypisania może dotyczyć kilku | ||
| - | zmiennych. Pojedyncze instrukcje mogą | ||
| - | opcjonalnie kończyć się średnikiem. | ||
| - | Listing 3 ilustruje wykorzystanie funkcji, | ||
| - | zastosowanie pętli oraz instrukcji warunkowych | ||
| - | na przykładzie funkcji wyznaczającej | ||
| - | wartość minimalną i maksymalną z trzech | ||
| - | liczb, oraz funkcji obliczającej pierwiastki | ||
| - | równania kwadratowego. | ||
| - | Jak widzimy w przykładzie, funkcje mogą | ||
| - | przyjmować i zwracać więcej niż jeden | ||
| - | parametr. Istnieje również możliwość deklarowania | ||
| - | funkcji rekurencyjnych (Listing | ||
| - | 4). | ||
| - | **Listing 3** - przykład stosowania funkcji i warunków logicznych, funkcja obliczająca silnie. | + | **Listing 3** - przykład stosowania funkcji i warunków logicznych, funkcja rekurencyjna obliczająca silnie. |
| <code cpp> | <code cpp> | ||
| Linia 141: | Linia 119: | ||
| wartością //nil//. Elementami tablicy mogą być wszystkie wartości podstawowych typów Lua. Oznacza to, że również mogą to być omawiane w tym miejscu Tablice. Pozwala to na tworzenie takich struktur jak lista, wektor, kolejka czy stos. | wartością //nil//. Elementami tablicy mogą być wszystkie wartości podstawowych typów Lua. Oznacza to, że również mogą to być omawiane w tym miejscu Tablice. Pozwala to na tworzenie takich struktur jak lista, wektor, kolejka czy stos. | ||
| - | Listing 5 pokazuje przykłady | + | Listing 4 pokazuje przykłady wykorzystania tablic w Lua realizując proste zbiory danych, listę jednokierunkową, czy strukturę zawierającą zarówno atrybuty jak i metody. |
| - | wykorzystania tablic w Lua realizując | + | |
| - | proste zbiory danych, listę jednokierunkową, | + | |
| - | czy strukturę zawierającą zarówno atrybuty | + | |
| - | jak i metody. | + | |
| Linia 181: | Linia 154: | ||
| + | === Biblioteka standardowa Lua === | ||
| + | Lua jak każdy porządny język, wyposażona została w bogatą standardową bibliotekę zawierającą bogaty zestaw narzędzi wyższego poziomu. Należą do niej następujące moduły: | ||
| + | |||
| + | * funkcje wejścia/wyjścia; | ||
| + | * funkcje systemowe; | ||
| + | * operacje na łańcuchach znaków; | ||
| + | * operacje na tablicach; | ||
| + | * obsługa wątków; | ||
| + | * funkcje matematyczne; | ||
| + | |||
| + | Poniższy kod pokazuje kilka przykładów wykorzystania biblioteki standardowej. | ||
| + | |||
| + | **Listing 5** Wykorzystanie biblioteki standardowej Lua | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | -- losowanie liczb | ||
| + | math.randomseed(os.time()) | ||
| + | print(math.random(10)); -- wyświetlenie liczby wylosowanej z przedziału [1,10] | ||
| + | |||
| + | -- obliczenie wartości cos(pi/5) | ||
| + | print(math.cos(math.pi*0.2)); | ||
| + | |||
| + | |||
| + | -- zapis do pliku | ||
| + | f = assert(io.open("output.txt", "w")) | ||
| + | f:write("test"); | ||
| + | f:close(); | ||
| + | |||
| + | </code> | ||
| ==== Integracja z C++ ==== | ==== Integracja z C++ ==== | ||
| + | |||
| + | Zapoznaliśmy się już z podstawami języka Lua, część przejść do najważniejszej sprawy czyli integracji z językiem C++. | ||
| === Przygotowanie do pracy z Lua === | === Przygotowanie do pracy z Lua === | ||
| - | === Wywoływanie funkcji Lua w C++ === | + | W celu rozpoczęcia pracy z Lua musimy wykonać dwie następujące operacje: |
| + | |||
| + | - Dołączenie do projektu skompilowaną bibliotekę Lua oraz dołączyć w kodzie nagłówki Lua (lua.h, lualib.h i lauxlib.h) | ||
| + | - Należy zapamiętać, że skrypty Lua wykonywane są na maszynie wirtualnej, musimy więc ją zainicjować. | ||
| + | |||
| + | Prosty przykład ukazujący wspomniane operacje i wywołujący z poziomu kodu C++ skrypt Lua pokazany jest na Listingu 6. | ||
| + | |||
| + | **Listing 6** Inicjalizacja maszyny wirtualnej Lua i wywołanie skryptu Lua z poziomu kodu C++ | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | #include <iostream> | ||
| + | |||
| + | // dołączenie nagłówków Lua | ||
| + | extern "C" | ||
| + | { | ||
| + | #include "lua.h" | ||
| + | #include "lualib.h" | ||
| + | #include "lauxlib.h" | ||
| + | } | ||
| + | |||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // utworzenie maszyny wirtualnej Lua. | ||
| + | lua_State* L = lua_open(); | ||
| + | |||
| + | // inicjalizacja standardowych bibliotek | ||
| + | luaL_openlibs(L); | ||
| + | |||
| + | // wczytanie skryptu Lua | ||
| + | if (luaL_dofile(L, "zpr.lua")) | ||
| + | { | ||
| + | // Walidacja wcztania skryptu | ||
| + | std::cout << "Error while running script: " << lua_tostring(L, -1) << std::endl; | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | // zamknięcie maszyny wirtualnej | ||
| + | lua_close(L); | ||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | </code> | ||
| + | |||
| + | |||
| + | === Wywoływanie funkcji Lua w kodzie C++ === | ||
| + | |||
| + | Potrafimy już z poziomu kodu C++ zainicjalizować maszynę wirtualną Lua i uruchomić skrypt napisany w Lua. Przejdźmy krok dalej - spróbujmy wywołać funkcję zdefiniowaną w skrypcie Lua z poziomu kodu C++. Zacznijmy od przykładowej funkcji obliczającą różnicę dwóch liczb. | ||
| + | |||
| + | **Listing 7** Funkcja Lua obliczającą różnicę dwóch liczb. | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | --sub.lua | ||
| + | |||
| + | function(x,y) | ||
| + | return x - y | ||
| + | end | ||
| + | |||
| + | |||
| + | </code> | ||
| + | |||
| + | Aby umożliwić wywoływanie funkcji ze skryptu Lua musimy zdefiniować kodzie C++ funkcję, w której odłożymy na stos parametry funkcji, a następnie | ||
| + | zdejmiemy ze stosu wartość zwracaną przez funkcję. Ilustruje to poniższy przykład: | ||
| + | |||
| + | **Listing 8** Przykład wywołania funkcji Lua w kodzie C++. | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | #include <iostream> | ||
| + | |||
| + | // dołączenie nagłówków Lua | ||
| + | extern "C" | ||
| + | { | ||
| + | #include "lua.h" | ||
| + | #include "lualib.h" | ||
| + | #include "lauxlib.h" | ||
| + | } | ||
| + | |||
| + | |||
| + | // Interpretator Lua | ||
| + | lua_State* L; | ||
| + | |||
| + | |||
| + | // Funkcja wywołującą funkcję ze skryptu Lua i zwracająca otrzymany wynik | ||
| + | int luaSub(int x, int y) | ||
| + | { | ||
| + | |||
| + | int sub = 0; | ||
| + | |||
| + | // nazwa funkcji w pliku sub.lua | ||
| + | lua_getglobal(L, "sub"); | ||
| + | |||
| + | // pierwszy argument | ||
| + | lua_pushnumber(L, x); | ||
| + | |||
| + | // drugi agrument | ||
| + | lua_pushnumber(L, y); | ||
| + | |||
| + | // wywołanie funkcji z dwoma argumentami i jedną wartością zwracaną | ||
| + | lua_call(L, 2, 1); | ||
| + | |||
| + | // pobranie wyniku i zdjęcie ze stosu | ||
| + | sub = static_cast<int>(lua_tointeger(L, -1)); | ||
| + | |||
| + | lua_pop(L, 1); | ||
| + | return sub; | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | int sub = 0; | ||
| + | |||
| + | // utworzenie maszyny wirtualnej Lua. | ||
| + | L = lua_open(); | ||
| + | |||
| + | // inicjalizacja standardowych bibliotek | ||
| + | luaL_openlibs(L); | ||
| + | |||
| + | // wczytanie skryptu Lua | ||
| + | if (luaL_dofile(L, "sub.lua")) | ||
| + | { | ||
| + | // Walidacja wczytania skryptu | ||
| + | std::cout << "Error while running script: " << lua_tostring(L, -1) << std::endl; | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | // wywołanie funkcji | ||
| + | sub = luaSub( 10, 15 ); | ||
| + | |||
| + | std::cout << "Substraction: " << sub << std::endl; | ||
| + | |||
| + | // zamknięcie maszyny wirtualnej | ||
| + | lua_close(L); | ||
| + | return 0; | ||
| + | |||
| + | } | ||
| + | |||
| + | </code> | ||
| + | |||
| + | |||
| + | === Wywoływanie funkcji C++ w kodzie Lua === | ||
| + | |||
| + | Spróbujmy zrobić wykonać to samo zadanie odwrotni. Wywołajmy funkcję napisaną w C++ w kodzie Lua. Funkcje w Lua są wywoływane używając wskaźnika na funkcję: | ||
| + | |||
| + | ''typedef int (*lua_CFunction) (lua_State *L);'' | ||
| + | |||
| + | Wynika z tego, że funkcje przyjmują jako argument interpretator Lua i zwracają wartość int. Napiszmy funkcję w C++, która będzie liczyła sumę liczb przekazanych do funkcji, których liczba będzie zmienna: | ||
| + | |||
| + | **Listing 9** Funkcja liczącą sumę podanych liczb w C++ wywoływana z poziomu kodu Lua. | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | |||
| + | |||
| + | #include <iostream> | ||
| + | |||
| + | // dołączenie nagłówków Lua | ||
| + | extern "C" | ||
| + | { | ||
| + | #include "lua.h" | ||
| + | #include "lualib.h" | ||
| + | #include "lauxlib.h" | ||
| + | } | ||
| + | |||
| + | |||
| + | // Interpretator Lua | ||
| + | lua_State* L; | ||
| + | |||
| + | // Funkcja przygotowana do wywołania w kodzie Lua | ||
| + | static int suma(lua_State *L) | ||
| + | { | ||
| + | // pobranie liczby argumentów | ||
| + | int n = lua_gettop(L); | ||
| + | |||
| + | int suma = 0; | ||
| + | |||
| + | // sumowanie argumentów | ||
| + | for (int i = 0; i < n; ++i) | ||
| + | suma += lua_tonumber(L, i); | ||
| + | |||
| + | // zwrócenie sumy | ||
| + | lua_pushnumber(L, suma) | ||
| + | |||
| + | // zwracamy ilość wartości zwracanych przez funkcję | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | |||
| + | int main() | ||
| + | { | ||
| + | int sub = 0; | ||
| + | |||
| + | // utworzenie maszyny wirtualnej Lua. | ||
| + | L = lua_open(); | ||
| + | |||
| + | // inicjalizacja standardowych bibliotek | ||
| + | luaL_openlibs(L); | ||
| + | |||
| + | // rejestracja funkcji suma pod nazwą f_suma | ||
| + | lua_register(L, "f_suma", suma); | ||
| + | |||
| + | // wczytanie skryptu Lua | ||
| + | if (luaL_dofile(L, "zpr.lua")) | ||
| + | { | ||
| + | // Walidacja wczytania skryptu | ||
| + | std::cout << "Error while running script: " << lua_tostring(L, -1) << std::endl; | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | // zamknięcie maszyny wirtualnej | ||
| + | lua_close(L); | ||
| + | return 0; | ||
| + | |||
| + | } | ||
| + | |||
| + | </code> | ||
| + | |||
| + | |||
| + | **Listing 10** Przykład wywołania w skrypcie Lua funkcji napisanych w C++ | ||
| + | <code cpp> | ||
| + | |||
| + | --zpr.lua | ||
| + | suma = f_suma(10, 20, 30, 40, 50) | ||
| + | print("Suma wynosi: ", suma) | ||
| + | </code> | ||
| - | === Wywoływanie funkcji C++ w Lua === | ||
| - | BUUU | ||
| ==== Więcej informacji ==== | ==== Więcej informacji ==== | ||