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. |
|
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. |
|
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). |
|
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. |
|
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:
lua_getfield( L, LUA_GLOBALSINDEX, "min" ); lua_pushinteger( L, 3 ); lua_pushinteger( L, 6 ); lua_call( L, 2, 1 ); int result = lua_tonumber( L, - 1 ); lua_pop( L, 1 );
Przykład podałem bez obsługi błędów, a obiekty globalne można też pobierać inaczej. Ale powinno działać. |
|
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ę. |
|
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: void Console::DoString( std::string str ) { 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" ) { for( int i = parameter_idx; i < str.length(); i++ ) { if( str[ i ] != '\"' && str[ i ] != ')' ) parameter1 += str[ i ]; } for( int i = 0; i < parameter1.length() - 1; i++ ) { 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; } } 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 = ""; }
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: 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. |
|
michalp |
» 2010-10-06 18:54:56 A co wrzucasz na stos? Powinieneś wrzucić wartość zmiennej a nie jej identyfikator (czyli string). |
|
« 1 » 2 |