Narzędzia użytkownika

Narzędzia witryny


c_i_lua

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Next revision
Previous revision
c_i_lua [2010/12/28 18:42]
sjablon1
c_i_lua [2010/12/29 12:22] (aktualna)
sjablon1
Linia 23: Linia 23:
  
 Strona ma na celu ukazanie sposobów i możliwości integracji języków C++ oraz Lua, jednak przedstawię krótko podstawy języka Lua wraz z przykładami. W celu dogłębnego poznania składni i możliwość języka polecam dokumentacje umieszczoną na stronie internetowej. Strona ma na celu ukazanie sposobów i możliwości integracji języków C++ oraz Lua, jednak przedstawię krótko podstawy języka Lua wraz z przykładami. W celu dogłębnego poznania składni i możliwość języka polecam dokumentacje umieszczoną na stronie internetowej.
 +
 +Na początek standardowy Hello World (Listing 1)
 +
 +**Listing 1** - program Hello World w Lua
 +
 +<code cpp>
 +
 +-- HelloWorld.lua
 +print("​Hello from Lua!"​);​
 +--[[
 +Przykład komentarza
 +umieszczonego w kilku liniach
 +]]
 +
 +</​code>​
 +
  
 === Konwencje leksykalne === === Konwencje leksykalne ===
  
-// wypunktować! 
   * W języku Lua identyfikatory mogą się składać z dowolnego łańcucha znaków alfanumerycznych lub znaku _.   * W języku Lua identyfikatory mogą się składać z dowolnego łańcucha znaków alfanumerycznych lub znaku _.
-  * Ograniczeniami są: zakaz rozpoczynania identyfikatora od cyfry oraz słowa zastrzeżone jak //and//, //or//, //break//, //else// itp.  +  * Ograniczeniami są: zakaz rozpoczynania identyfikatora od cyfry oraz słowa zastrzeżone jak //and//, //or//, //break//, //else// itp. 
-   ​+  * Lua rozróżnia wielkość liter, więc For będzie oznaczał identyfikator zaś for będzie dotyczył pętli. 
 +  * Komentarze rozpoczyna się podwójnym myślnikiem ​ i działa analogicznie jak  w C++, ignorowane są wszystkie znaki, aż do końca linii. 
 +  * Istnieje również możliwość komentowania całego bloku kodu na kształt znanych z języka C, które w Lua zastąpione jest ciągiem --[[".
  
-Lua rozróżnia wielkość liter, więc For będzie oznaczał identyfikator zaś for będzie dotyczył pętli. Komentarze rozpoczyna się podwójnym myślnikiem -- i działa analogicznie jak // w C++, ignorowane są wszystkie znaki, aż do końca linii. Istnieje również możliwość komentowania całego bloku kodu na kształt znanych z języka C /* .. */, które w Lua zaczynamy --[[" i kończymy "]]. 
  
 === Typy danych i wyrażenia === === Typy danych i wyrażenia ===
  
-//​wypunktować 
  
 W Lua podobnie jak w innych językach skryptowych nie deklarujemy typów zmiennych. Zamiast tego każda zmienna ma dynamiczny typ określany przez jej wartość. W Lua podobnie jak w innych językach skryptowych nie deklarujemy typów zmiennych. Zamiast tego każda zmienna ma dynamiczny typ określany przez jej wartość.
Linia 41: Linia 56:
 Istnieje 8 podstawowych typów danych: Istnieje 8 podstawowych typów danych:
  
 +  * //nil// - przyjmuje jedną wartość nil, która określa brak konkretnej wartości (często nil jest stosowany do określenia zmienną niezainicjalizowaną);​
 +  * //boolean// - standardowe wartości boolowskie true/false;
 +  * //number// - liczba rzeczywista,​ zmiennoprzecinkowa;​
 +  * //string// - standardowy łańcuch znaków;
 +  * //​userdata//​ - typ danych pozwalajacy na przetrzymywanie dowolnych danych z języka C(np. wskaźników);​
 +  * //​function//​ - ciąg wykonywalnych instrukcji, funkcje mogą być deklarowane wewnątrz innych funkcji lub być zwracane z innej funkcji
 +  *// thread// - wątek w Lua;
 +  * //table// - tablica asocjacyjna(więcej informacji w dalszej części strony);
  
-nil – przyjmuje jedną wartość nil, która +Ciekawym mechanizmem języka jest poleceniem //type// pozwalające na sprawdzenie typu zmiennejPrzykład pokazano ​na Listingu 2.
-określa brak konkretnej wartości (często +
-nil jest stosowany do określenia +
-zmienną niezainicjalizowaną);​ +
-• boolean – przyjmuje standardowe +
-wartości boolowskie, czyli true lub +
-false; +
-• number – liczba reprezentująca wartości +
-rzeczywiste (zmiennoprzecinkowe);​ +
-liczby możemy zapisywać ​na różne +
-sposoby, np.: 18, 3.141592, 1.23e12, +
-4.18e-3; +
-• string – standardowy ​łańcuch znaków, +
-np. "What is your name?";​ +
-• userdata – typ danych umożliwiający +
-przetrzymywanie dowolnych danych z +
-języka C (np. wskaźników) w strukturach +
-Lua; +
-• function – funkcje zdefniniowane jako +
-wykonywalny ciąg instrukcji; funkcje +
-mogą być deklarowane wewnątrz +
-innych funcji, mogą być argumentami +
-innych funkcji, lub być zwracane z innej +
-funkcji; +
-• thread – wątek w Lua – z uwagi na charakter +
-niniejszego artykułu nie będziemy +
-omawiać wątków w Lua; +
-• table – tablica asosjacyjna będąca najcięższym +
-orężem Lua; dokładny opis tablic +
-znajduje się w dalszej części. +
-W dowolnym miejscu skryptu możemy +
-sprawdzić typ danej zmiennej poleceniem +
-type (jak pokazano w Listingu 2). +
-Lua, jak przystało na porządny język programowania,​ +
-oferuje również różnego rodzaju +
-operatory do definiowania wyrażeń. Wyróżniamy:​ +
-• operatory arytmetyczne,​ czyli + (dodawanie),​ +
-- (odejmowanie),​ * (mnożenie),​ +
-/ (dzielenie),​ % (modulo) i ^ (potęgowanie);​ +
-• operatory porównania,​ czyli == (równe), +
-~= (różne), < (mniejsze), > (większe),​ +
-<= (mniejsze lub równe), >= (większe lub +
-równe); +
-• operatory logiczne, takie jak and (część +
-wspólna), or (suma logiczna), not (negacja).+
  
-Instrukcje i funkcje +**Listing 2** - przykład polecenia type w Lua. 
-Lua obsługuje standardowy zestaw instrukcji + 
-podobnych do tych stosowanych w zyku +<code cpp> 
-Pascal ​czy C. Istnieje możliwość definiowania + 
-bloków instrukcji objętych słowami kluczowymi +print(type(a)) --> nil (zmienna '​a'​ nie została zainicjalizowana) 
-do i end, które ​można kontrolować +a = 10 
-poprzez break czy returnNa listę pojedynczych +print(type(a)) --> number 
-instrukcji składają się: +a = print 
-• instrukcje przypisania ​=; +a(type(a)) --> function 
-• instrukcje warunkoweif/​elseif/​else/+ 
 +</​code>​ 
 + 
 + 
 +W Lua dostępne są następujące operatory:​ 
 + 
 +  * Operatory arytmetyczne:​ +, -, *, /; 
 +  * Operatory porównania:​ ==, ~=, <, >, <=, >=- 
 +  * Operatory logiczne: //and//, //or//, //not// 
 + 
 +=== Instrukcje i funkcje ​=== 
 + 
 +Lua posiada standardowe instrukcje znane z 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;​ 
 + 
 + 
 +**Listing 3** - przykład stosowania funkcji ​warunków logicznych, funkcja rekurencyjna obliczająca silnie. 
 + 
 +<code cpp> 
 + 
 +-- obliczenie n! 
 +function factorial (n) 
 +if n == 1 then 
 +return 1; 
 +else 
 +return n * factorial(n-1);​ 
 +end 
 +end 
 +-- obliczenie 5! 
 +print(factorial(5));​ --> 120 
 + 
 +</​code>​ 
 + 
 +=== Tablice === 
 + 
 +Najistotniejszymi strukturami danych w Lua są tablice asocjacyjne reprezentowane przez kolekcję par (kluczwartość). Kluczem ​może być wszystko poza 
 +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 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. 
 + 
 + 
 +**Listing 4** - przykład wykorzystania tablic do realizacji zbiorów danych. 
 + 
 +<code cpp> 
 + 
 + 
 +-- prosty wektor liczb 
 +squares ​{1, 4, 9, 16, 25, 36, 49, 64, 81} 
 +-- zbiór danych 
 +creature = { name = "​Ghoul",​ health = 100 } 
 +print(creature["​name"​])--> Ghoul 
 +print(creature.name);​ --> Ghoul 
 +-- lista 
 +list = nil; 
 +list = {next = listvalue = 2}; 
 +list = {next = list, value = "​test"​};​ 
 +list = {next = list, value = math.pi}; 
 +ptr = list; 
 +while ptr do 
 +print(ptr.value);​ 
 +ptr = ptr.next; 
 +end; --> 3.141592 test 2 
 +-- struktura/klasa 
 +Vec3 = {}; 
 +Vec3.new = function(x, y, z) 
 +return {x=x, y=y, z=z, length=function() return math.sqrt(x*x+y*y+z*z) end;}
 end; end;
-• pętlefor/do/endwhile/​do/​end,​ repeat/ +v = Vec3.new(424)
-until/+print(v:​length()); --> 6
-• 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).+
  
-Tablice +</​code>​
-Tablice są najistotniejszymi strukturami +
-danych w Lua. Są one reprezentowane przez kolekcję par (klucz, wartość), gdzie +
-kluczem może być wszystko poza wartością +
-nil. Elementami tablicy mogą być +
-wszystkie wartości podstawowych typów+
  
-Lua, czyli także same tablice. Dzięki temu + 
-mechanizm tablicy umożliwia definiowanie +=== Biblioteka standardowa ​Lua === 
-użytkownikowi dowolnych struktur + 
-danych, które mogą być utożsamiane z elementami +Lua jak każdy porządny językwyposażona została w bogatą standardową bibliotekę zawierającą bogaty ​zestaw ​narzędzi wyższego poziomu. Należą do niej następujące moduły: 
-takimi jak: listawektor, kolejka, + 
-zestaw ​czy stos. +  * funkcje wejścia/​wyjścia;​ 
-W tradycyjnych językach programowania +  * funkcje systemowe; 
-jakimi są C czy Pascal w większości przypadków +  * operacje na łańcuchach znaków; 
-złożone struktury danych reprezentowane +  * operacje na tablicach;​ 
-są właśnie przez dynamiczne listy lub +  * obsługa ​tków; 
-wektory prostych typów danych. Tablice ​w +  * funkcje matematyczne;​ 
-Lua umożliwiają implementację o wiele bardziej + 
-złożonych i elastycznych struktur, stworzonych +Poniższy kod pokazuje ​kilka przykładów wykorzystania ​biblioteki standardowej. 
-specjalnie na potrzeby rozwiązania + 
-danego zagadnienia. Listing 5 pokazuje przykłady +**Listing 5** Wykorzystanie biblioteki standardowej ​Lua 
-wykorzystania ​tablic w Lua realizując + 
-proste zbiory danych, listę jednokierunkową+<code cpp> 
-czy strukturę zawierającą zarówno atrybuty + 
-jak i metody.+-- 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 ====
c_i_lua.1293558136.txt.gz · ostatnio zmienione: 2010/12/28 18:42 przez sjablon1