Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Lua i C++] Kilka pytań

Ostatnio zmodyfikowano 2010-10-10 08:35
Autor Wiadomość
programista12
Temat założony przez niniejszego użytkownika
[Lua i C++] Kilka pytań
» 2010-10-02 09:58:21
Mam kilka pytań dotyczących Lua i C++:
1. Czy da się używać funkcji z innego skryptu (np. funkcji ze skryptu a w skrypcie b)? Jeżeli tak, to jak to zrobić?
2. W swoich grach chciałbym zrobić konsolę, z której można by wywoływać funkcje ze skryptu Lua. Mógłby mi ktoś poradzić jak to zrobić? Klasę konsoli napiszę sam, ale nie wiem jak wywoływać funkcje ze skryptu Lua z poziomu konsoli. Do łączenia Lua z C++ mam zamiar użyć luabind.

Proszę o pomoc, z góry dziękuję za odpowiedzi.
P-22586
DejaVu
» 2010-10-02 19:52:11
Zacznij od skonfigurowania biblioteki i poczytania krótkiego kursu pokazującej jak z niej korzystać. Pytanie jest ogólne. To tak jak by tłumaczyć komuś co to jest pętla for i jak z niej korzystać kto nie ma pojęcia o programowaniu.
P-22593
programista12
Temat założony przez niniejszego użytkownika
» 2010-10-03 09:39:36
Na pierwsze pytanie odpowiedź znalazłem w internecie. Trzeba w skrypcie dodać linijkę:
dofile "nazwa_skryptu.lua"

Jednak nie wiem jak zrobić coś podobnego do konsoli Lua z filmiku Adventures in Game Development Chapter 13 Part 3. Chodzi mi o to, że nie wiem jak przenieść funkcje z C++ do Lua. W internecie znalazłem 2 artukuły (pierwszy i drugi), ale nic mi nie wychodzi.

Proszę o wyjaśnienie krok po kroku jak to zrobić, bo sam nie dam rady.

PS:
Ja wiem mniej więcej jak korzystać z luabind (z tego artykułu się nauczyłem).
P-22596
DejaVu
» 2010-10-03 18:27:32
Z tego co pamiętam na naszym forum było może ze 3 użytkowników którzy interesowali się lua trochę więcej no więc raczej słabo może być z jakąś pomocą w tej materii.
P-22598
michalp
» 2010-10-03 19:33:04
Najpierw musisz wrzucić funkcję (którą chcesz wywołać) na stos. Jeżeli funkcja jest globalna to wystarczy wywołać funkcję lua_getfield z drugim argumentem jako LUA_GLOBALSINDEX (i oczywiście trzecim argumentem jako nazwą funkcji), np:

lua_getfield( L, LUA_GLOBALSINDEX, "min" );

Następnie wrzucić argumenty na stos (w normalnej kolejności, nie w odwrotnej). Potem wywołać funkcję za pomocą lua_call. Całość wyglądać będzie np. tak:

C/C++
lua_getfield( L, LUA_GLOBALSINDEX, "min" ); // wrzucamy funkcję min na stos
lua_pushinteger( L, 3 ); // wrzucamy na stos pierwszy argument
lua_pushinteger( L, 6 ); // wruczamy na stos drugi argument
lua_call( L, 2, 1 ); // wywołujemy funkcję min z dwoma argumentami i jednym zwracanym obiektem
int result = lua_tonumber( L, - 1 ); // zapisujemy wynik
lua_pop( L, 1 ); // zdejmujemy ze stosu jeden argument

Przykład podałem bez obsługi błędów, a obiekty globalne można też pobierać inaczej. Ale powinno działać.
P-22600
programista12
Temat założony przez niniejszego użytkownika
» 2010-10-03 20:17:47
Dzięki za odpowiedź! Twój sposób działa. Teraz pokombinuję trochę i jak będę miał jakieś pytania, to napiszę.
P-22602
programista12
Temat założony przez niniejszego użytkownika
» 2010-10-06 18:10:00
W końcu udało mi się skodzić konsolę, jednak niezbyt mi wyszło wykonywanie poleceń Lua. Przykładowo chcę mieć funkcję, która wypisuje tekst w konsoli. Napisałem tą funkcję:
function Console_Print(text)
return text
end
I jeszcze dosyć skomplikowany kod funkcji wykonującej polecenie Lua:
C/C++
void Console::DoString( std::string str ) // Console to klasa konsoli
{
    std::string func_name = "";
    std::string parameter1 = "";
    std::string parameter2 = "";
    std::string parameter3 = "";
    std::string parameter4 = "";
    int parameter_idx;
    int num_to_print;
    std::string str_to_print;
    bool is_number = false;
    for( int i = 0; i < str.length(); i++ )
    {
        if( str[ i ] != '(' )
        {
            func_name += str[ i ];
        }
        else
        {
            parameter_idx = i + 1;
            break;
        }
    }
    if( func_name == "Console_Print" )
    {
        //pobieranie parametrów funkcji Console_Print()
        for( int i = parameter_idx; i < str.length(); i++ )
        {
            if( str[ i ] != '\"' && str[ i ] != ')' )
                 parameter1 += str[ i ];
           
        }
        //sprawdzanie, czy parametr nie jest przypadkiem liczbą
        for( int i = 0; i < parameter1.length() - 1; i++ )
        {
            //jeżeli tak
            if( parameter1[ i ] == '0' || parameter1[ i ] == '1' || parameter1[ i ] == '2' || parameter1[ i ] == '3' ||
            parameter1[ i ] == '4' || parameter1[ i ] == '5' || parameter1[ i ] == '6' || parameter1[ i ] == '7' ||
            parameter1[ i ] == '8' || parameter1[ i ] == '9' )
            {
                if( parameter1[ i + 1 ] == '0' || parameter1[ i + 1 ] == '1' || parameter1[ i + 1 ] == '2' || parameter1[ i + 1 ] == '3' ||
                parameter1[ i + 1 ] == '4' || parameter1[ i + 1 ] == '5' || parameter1[ i + 1 ] == '6' || parameter1[ i + 1 ] == '7' ||
                parameter1[ i + 1 ] == '8' || parameter1[ i + 1 ] == '9' )
                {
                    is_number = true;
                    num_to_print = StrToInt( parameter1 );
                    break;
                }
            }
            //jeżeli nie
            else
            {
                is_number = false;
                break;
            }
        }
        lua_getfield( L, LUA_GLOBALSINDEX, "Console_Print" );
        if( is_number == true )
             lua_pushinteger( L, num_to_print );
        else
             lua_pushstring( L, parameter1.c_str() );
       
        lua_call( L, 1, 1 );
        Console::PrintText( lua_tostring( L, - 1 ) );
        lua_pop( L, 1 );
    }
    if( luaL_loadbuffer( L, str.c_str(), std::strlen( str.c_str() ), str.c_str() ) || lua_pcall( L, 0, 0, 0 ) )
    {
        std::string a = lua_tostring( L, - 1 );
        Console::PrintText( a );
        lua_pop( L, 1 );
    }
    cmd = ""; //czyszczenie zmiennej przechowującej wpisane polecenie
}
Jednak mam wrażenie, że mi ona nie wyszła, bo jak wpiszę "x = 10" i potem wpiszę "Console_Print(x)", to wypisuje "x" zamiast "10". Czy mógłby ktoś mi podpowiedzieć, jak ją napisać, żeby po wpisaniu "x = Dodaj(10,15)" i "Console_Print(x)" w konsoli wypisało 25, a nie x? Dodaj() to funkcja dodająca 2 liczby. Dodam, że w konsoli udało mi się to napisać. Kod:
C/C++
bool dostring( lua_State * L, std::string str )
{
    if( luaL_loadbuffer( L, str.c_str(), std::strlen( str.c_str() ), str.c_str() ) || lua_pcall( L, 0, 0, 0 ) )
    {
        std::string a = lua_tostring( L, - 1 );
        std::cout << a << "\n";
        lua_pop( L, 1 );
        return true;
    }
    return false;
}

void main()
{
    lua_State * L = lua_open();
    luaL_openlibs( L );
    luaL_dofile( L, "funkcje.lua" );
    bool exit = false;
    std::string cmd;
    while( !exit )
    {
        std::cout << ">";
        std::getline( std::cin, cmd );
        if( cmd == "!exit" )
        {
            exit = true;
        }
        else
        {
            dostring( L, cmd.c_str() );
            std::cout << std::endl;
        }
    }
    return;
}
Kod funkcji "dostring()" wziąłem z przykładów z biblioteki luabind.
P-22627
michalp
» 2010-10-06 18:54:56
A co wrzucasz na stos? Powinieneś wrzucić wartość zmiennej a nie jej identyfikator (czyli string).
P-22628
« 1 » 2
  Strona 1 z 2 Następna strona