SFML community forums

Help => General => Topic started by: Raincode on June 09, 2014, 10:22:00 am

Title: Loading Game Data with Lua
Post by: Raincode on June 09, 2014, 10:22:00 am
Hello,

I have the SFML Game Development Book and it says somewhere:
"Nowadays, it is very common to load gameplay information from external resources [...]
One possibility that has recently gained popularity consists of using script languages, most notably Lua [...]"

I am very interested in trying this, I actually already was before reading this, for loading some data like tables or something and also using it to code some game logic.

However, I have no clue what I need to get started, I guess I need a Lua interpreter, which I have now, but which libaries do I need? Is "Lua binding for C++" the correct term? If I know what I need, I can search for tutorials, documentation and stuff online and do it myself, but I am kind of missing a starting point.

Hope someone can help me

Kind Regards,
Raincode
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 09, 2014, 10:55:46 am
SFML doesn't provide tutorials for Lua, but there might be some files on the Wiki.

Otherwise, you can use www.lua.org as a starting point. I have made good experience with the LuaBridge (https://github.com/vinniefalco/LuaBridge) binding.
Title: Re: Loading Game Data with Lua
Post by: Jesper Juhl on June 09, 2014, 11:04:46 am
 Embedding Lua is simple (as it ought to be since that is what it was designed for).
It's basically just a matter of including lua.h, calling lua_open() and a few other details.
Google for "embedding Lua in C++" and you'll find lots of material to show you how to.
Title: Re: Loading Game Data with Lua
Post by: Raincode on June 09, 2014, 11:22:03 am
Hi,

thank you very much for your replies.

I think I'll be able to manage it. I am aware, that this isn't exactly the right forum, but since I read it in the book, I thought someone must know something.

LuaBridge seems promising, I'll try starting with that.
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 09, 2014, 06:37:09 pm
I am aware, that this isn't exactly the right forum, but since I read it in the book, I thought someone must know something.
I wrote the quoted passage in the book, and what I had in mind is more or less what I wrote in the last post ;)

Note that there are many possibilities to use Lua in C++. Either you use directly the C library, or one of the various C++ bindings such as LuaBridge. There's a list of C++ bindings (http://lua-users.org/wiki/BindingCodeToLua) with really many entries. That wiki is quite good in general for various Lua-related things.

I've initially used LuaBind, it's nice but really heavy, with the Boost dependency and huge compile times. So I've looked for a few alternatives and so far, LuaBridge was the binding with the best trade-off between flexibility and complexity.
Title: Re: Loading Game Data with Lua
Post by: select_this on June 09, 2014, 06:41:35 pm
The only thing that would concern me with LuaBridge is that there hasn't been anything significant changed since Oct 2013, and there are quite a few issues and pull requests with little to no activity. The maintainer appears to be fairly active elsewhere.
Title: Re: Loading Game Data with Lua
Post by: dabbertorres on June 09, 2014, 09:36:07 pm
A new, very nice binding library is Selene (https://github.com/JeremyOng/Selene). I've found it very easy to use. It's pretty easy to navigate the source and add your own improvements as well.
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 09:14:52 am
A new recent, very nice binding library is Selene (https://github.com/JeremyOng/Selene).
This looks really promising. C++11 would allow to simplify a lot of things.

I definitely have to look closer at Selene, and possibly also a few other C++11 Lua bindings. It seems like that list changed a bit since I last read it. Thanks for the hint!
Title: Re: Loading Game Data with Lua
Post by: Raincode on June 10, 2014, 11:16:53 am
Yes definately thank you, I will check this Selene library then, because I just came here to complain about various compilation errors, simply by including the LuaBridge library :D

edit:

huum, so does the selene library...
such as:
error: expected ';' at end of member declaration
     Selector&& operator[](const char *name) && {
                                           ^
error: expected unqualified-id before '{' token
     Selector&& operator[](const char *name) && {
                                                ^
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 11:28:51 am
These are rvalue reference qualifiers. Apparently your compiler does not support all the needed C++11 features.

Out of interest, what compilation errors did you get at LuaBridge?
Title: Re: Loading Game Data with Lua
Post by: Raincode on June 10, 2014, 05:57:15 pm
If that is the case, which gcc version is required at least to support these features? I believe I have  GCC 4.8.1

The error with LuaBridge:
error: too many arguments to function 'const char* lua_pushstring(lua_State*, const char*)'
     lua_pushstring (L, str.c_str(), str.size());
                                               ^

some warnings:
warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
   inline void* const getPointer ()
                                  ^
Title: Re: Loading Game Data with Lua
Post by: Jesper Juhl on June 10, 2014, 06:18:58 pm
Are you passing -std=c++11 to the compiler to enable C++11 support?
Title: Re: Loading Game Data with Lua
Post by: Raincode on June 10, 2014, 06:39:43 pm
Definately, since not doing so gives another error. Additionally, the following program compiles and runs without problems:

int main()
{   
    std::vector<int> nums(1);
    nums[0] = 99;
    for (auto i : nums) std::cout << i;
}

Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 08:19:09 pm
The LuaBridge error is fixed by this pull request (https://github.com/vinniefalco/LuaBridge/pull/68). It's a bit unfortunate that Vinnie Falco is not active anymore, I also have one PR and one issue pending...

I'm not sure if and when the rvalue qualifiers have been implemented for g++, but you can easily research that. Maybe you need to simplify the code a bit (or contact the Selene author).
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 08:24:01 pm
Where is that error coming from? pushstring takes string, pushlstring takes string and size. Why would there be error like that in LuaBridge? Even Lua 5.1 and 5.0 have these functions like that, I think even 4.0 has and that was 14 years ago...
Cleared up by Nexus link.

The warning is saying that the function returns a const void pointer (NOT pointer to const void) which makes no sense, because you can simply copy it into another variable and have non const pointer to non const void. The 'const' there literally does nothing. It's as if the * was misplaced: http://www.stroustrup.com/bs_faq2.html#constplacement

You'd be better off without using a binding for now, many of them do weird things like automatically create metatables and so on, this is really bad if you don't understand what the Lua logic behind that is. It's too much of a headache to try to learn all three - language, C API and binding API all at once.

Selene is good, clear, small and easy but still misses many things, it's better for loading data than real logic, I have to admit, data loading is extremely simple in it. It also is doing the 'magic' and taking away a lot of power you'd get learning C API. Using Selene's API you couldn't write a function to take advantage of Lua errors or overloading on amount/type of arguments passed without the C API.

Just use raw C API for a while, it's really not hard to use, and try to not mix the languages a lot, minimizing the amount of Lua <-> C++ action is a Good Thing according to both Lua and LuaJIT users and developers. Not only you'd not understand what the library binding Lua is giving you, you'd also probably not need it, it's better to take small steps and convert interesting bits of logic to Lua than suddenly attempting to use it in a C++ program like it's Unreal Script and coding every single bit of code in it. That is possible (Don't Starve uses idiotic amounts of Lua code for everything version 5.1 and no JIT I think which opens room for mods and maybe LuaJIT could combat the speed of Unreal Script, definitely not the tools, when used like that in an engine) but then you could just as well use existing Lua engine instead (like LOVE).

Just learn most of the raw C API (it's simple once you get into it more) and how C references, userdata, types and (meta)tables work (by work I mean how to use them in both languages, not how they're implemented in VM itself which is in C) and you're pretty good off.
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 08:35:04 pm
You'd be better off without using a binding for now, many of them do weird things like automatically create metatables and so on, this is really bad if you don't understand what the Lua logic behind that is. It's too much of a headache to try to learn all three - language, C API and binding API all at once.
A good binding abstracts from the C interface, so you don't have to learn it. Of course you have to learn Lua (and maybe you get some insights about the C implementation when having a deeper look). But the only sane thing you can do with the C binding is writing another wrapper for it, unless you want to use verbose and error-prone boilerplate code all the time. In terms of productivity, I wouldn't recommend that -- but it may be an interesting experiment.

It also is doing the 'magic' and taking away a lot of power you'd get learning C API. Using Selene's API you couldn't write a function to take advantage of Lua errors or overloading on amount/type of arguments passed without the C API.
Selene is very young, so if more features are needed, I would rather choose another binding, there are enough of them. It depends of course on what you need and how much time you want to spend on making C++ bind to Lua.
Title: Re: Loading Game Data with Lua
Post by: Raincode on June 10, 2014, 08:57:11 pm
I was able to fix the error with LuaBridge, along with learning to check the issues on GitHub if something isn't working, which is good, so thanks.

I'll be off experimenting with that and soon noticing it's too much for me, until I finally start getting a good grasp of C++, but I am just too curious.

So thanks for the help, I really appreciate people answering all those questions I have
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 09:28:03 pm
What exactly is 'verbose and error prone' and needs 'abstraction' in Lua C API?
Only thing is that everything has to go through lua_CFunction...
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 09:31:41 pm
The Selene developer writes about it in his blog (http://www.jeremyong.com/blog/2014/01/10/interfacing-lua-with-templates-in-c-plus-plus-11/).

The Lua C API doesn't know higher-level concepts such as classes, stateful functions, etc; it provides only the low level interface for maximum flexibility. As a C++ user, you typically don't care about the stack and the way how Lua methods are implemented. Abstraction is the whole point of the C++ bindings.
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 09:41:26 pm
Translating arguments from one language types to another's is perfectly understandable, especially since Lua is dynamically typed and has no limit on amount of taken and returned variables. Even if you bound it all through 'magic' templates you might need or want to have overloads that depend on type or number or arguments, type checking, ability to throw errors and more than one return. C++ doesn't have any of that, it has to go through a protocol.

Lua by design has no 'classes', you can implement them yourself with metatable very easily but again you'll have to bind every method by hand to match lua_CFunction and it's protocol.
What exactly do you mean by a stateful function?
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 09:55:02 pm
I'm just saying that if you use C++, you don't always care about the protocol or the implementation details of Lua tables and stacks. Sometimes you simply want to map C++ variables, functions and classes to their Lua equivalents. In all these cases, it is much easier to use a C++ binding than the C API; there's a reason why so many people have written one.

"Stateful function" in the sense of function object that can carry additional data besides parameters. Such as captured variables in a lambda expression, or member variables in a functor class.
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 10:24:55 pm
Quote
I'm just saying that if you use C++, you don't always care about the protocol or the implementation details of Lua tables and stacks.
No, you are saying you always don't care about the protocol. The switch of word order is important.
This is what you originally said:
Quote
A good binding abstracts from the C interface, so you don't have to learn it.


Why are you so fixated on calling function calls 'implementation details'? This is worst use of the term I've ever seen. You don't have to care one bit how Lua tables, metatables and stack are implemented - you simply call functions that operate on them, but since this is C and avoids any pitfalls of keep ownership the objects are on a stack, not given to you wrapped in a class.
You don't even have to control the types, that is done by implementing functions, in Lua operations will cause errors unless overloaded (so a function expecting a pair of numbers can be given classes that overload all numeric operators) and in C you have a type checking functions that return the variable if it's there or long jump or exception out of the function directly to last pcall (in Lua or C). You actually can even attempt to pcall a nil variable or a table or anything, it'll error out, you don't have to care.
Sanity checks are not default but can be compiled in, since it's quite reasonable to expect a person to fix their code not to try and index a number like if it's a table and so on.
This is like saying loading a sf::Texture is 'implementation detail' why do I have to load texture and make sure it did load, all I want is a picture but evil Laurent is forcing these implementation details on me...
You do not need to know how GC works, how allocator works(you can implement own one, if needed, for better locality or less fragmentation/systemcalls overhead), how tables try to have array and hash part, how strings are interned(although if you use some to index something a lot, then you might want to reference it) and hashed, how coroutines work, how references work(except not to use int indexes in table that you use as reference holder) how anything works really.

Quote
there's a reason why so many people have written one.
Unfortunately, no. The spread of a habit doesn't allow direct conclusions about its quality.
(This is a quote, guess the original author)

Quote
Sometimes you simply want to map C++ variables, functions and classes to their Lua equivalents.
There are features you can't or don't want to map over, semi often too. I personally didn't map over Vector2i that I used for grid position in my PacMan clone to Lua, I used a pair of numbers instead, way easier and faster. Is there a silver bullet binding library, one that has little overhead, lots of control and doesn't 'lock out' any Lua feature while being simple and easy to use. Name please?


Quote
"Stateful function" in the sense of function object that can carry additional data besides parameters. Such as captured variables in a lambda expression, or member variables in a functor class.
Lua can overload call operator if you need exactly that, it can also create functions in coroutines that keep local variables to themselves between yields and a C function can have upvalues which are Lua values that the C function can access using C API.
There are three ways to achieve 'statefulness', is that enough to justify evil C API?
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 10:47:51 pm
Quote
Why are you so fixated on calling function calls 'implementation details'?
Not function calls, but big parts of the Lua C API. A truly abstract C++ binding could be written on top of a completely different backend (if there were one), still maintaining the same functionality.

Quote
This is like saying loading a sf::Texture is 'implementation detail'
No, it's not. You use sf::Texture directly all the time. It's rather like saying "stb_image" is an implementation detail... and yes, it is.

Quote
Unfortunately, no. The spread of a habit doesn't allow direct conclusions about its quality.
Instead of quoting me out of context, let's stay with the topic. There is a good reason why people write wrappers to abstract from C libraries in general, and the Lua C library in particular -- do I seriously have to explain it?

Quote
Is there a silver bullet binding library, one that has little overhead, lots of control and doesn't 'lock out' any Lua feature while being simple and easy to use.
There's never a silver bullet, choosing the right tools is always about trade-offs. In my case, I trade simplicity, type safety and genericity for some flexibility. But I'm always able to fall back to the C API in case I really need it, or even extend existing wrappers to fit the gap.

Quote
Lua can overload call operator if you need exactly that, it can also create functions in coroutines that keep local variables to themselves between yields and a C function can have upvalues which are Lua values that the C function can access using C API.
Yes, and compare the code needed to achieve that with equivalent code using a C++ Lua binding. Count the number of methods you need to know, and the number of places where you have to be extra careful to not make any mistakes.

Of course things are possible with the C API, otherwise no C++ binding could be written on top of it.

A good comparison is SFML and OpenGL. You can't achieve everything OpenGL does with SFML, because... SFML is an abstraction. If abstractions provided all the original features, the whole point of abstracting would be missed. But you can achieve a lot with SFML, and in a much faster and more productive way. I don't recommend the Lua C binding to Lua newcomers for the exact same reason why I don't recommend OpenGL to game development newcomers.
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 11:30:52 pm
Simply show your chosen binding and how it deals with all features and problems while being easier to use than original C API and not very heavy on the performance or compile times. You keep saying how much better, easier, safer and more generic it is and have not yet named it. Is it LuaBridge?
Quote
Not function calls, but big parts of the Lua C API.
Such as? Other than the stupid protocol that is quite simple in itself.

Quote
There's never a silver bullet (...) But I'm always able to fall back to the C API in case I really need it, or even extend existing wrappers to fit the gap.
But you just said via your advice that you 'don't have to learn it(C API)' a while ago because a 'good' binding abstracts it away. While at the same time I said a fair while ago that Selene is extremely fit for a particular purpose and my advice is to learn C API before any binding because that gives understanding of what the binding does, ability to read its code and eases the strain of learning by quite a lot. You are the one talking about silver bullets and completely eliminating an entire aspect of Lua.

Quote
Yes, and compare the code needed to achieve that with equivalent code using a C++ Lua binding. Count the number of methods you need to know, and the number of places where you have to be extra careful to not make any mistakes.
To use upvalues you need:
-checkers or getters of your values
-setters of your values
-lua_pushcclosure
-lua_upvalueindex
4 functions in total at a minimum, two used uniquely for that purpose, both easy to graps, and you have to be reasonably careful about what you pass in them or compile with api check, I don't know how extensive the checking is is. It's fairly easy.

Quote
do I seriously have to explain it?
Yes. Not everything is immediately better in C++ over C. Lots of things are but not everything. I've yet to see harsh criticism of C API and outcry for a 'truly abstract easy safe' binding such as yours, ever. I've instead seen it being compared to other scripts' C interfaces that are apparently worse.

Quote
If abstractions provided all the original features, the whole point of abstracting would be missed.
Then why do you want a simple and automatic way to bind your code to Lua 1:1? That is a kind of 'binding' and abstraction as well, script is not C++, not all that works in C++ works in Lua, not everything even should.
Quote
Sometimes you simply want to map C++ variables, functions and classes to their Lua equivalents.
Title: Re: Loading Game Data with Lua
Post by: Nexus on June 10, 2014, 11:39:38 pm
You are the one talking about silver bullets and completely eliminating an entire aspect of Lua.
No I'm not, please read my last post again if you got that impression. I explicitly mentioned that there will be a flexibility trade-off. I haven't measured performance, but I doubt there will be a huge difference, since C++ template metaprogramming and other abstractions don't automatically incur runtime overhead.

To use upvalues you need:
-checkers or getters of your values
-setters of your values
-lua_pushcclosure
-lua_upvalueindex
4 functions in total at a minimum, two used uniquely for that purpose, both easy to graps, and you have to be reasonably careful about what you pass in them or compile with api check, I don't know how extensive the checking is is. It's fairly easy.
If you call that fairly easy, the C++ version must be trivial.

You should really read the blog post of Selene I've linked in an earlier post, it explains exactly what I mean. Code is much shorter and expressive when you use a C++ binding. Again: for a flexibility trade-off.
Title: Re: Loading Game Data with Lua
Post by: FRex on June 10, 2014, 11:48:43 pm
Quote
No I'm not, please read my last post again if you got that impression. I explicitly mentioned that there will be a flexibility trade-off.
Nexus, pick, do you have to or do you not have to learn it? This is YOUR post:
Quote
A good binding abstracts from the C interface, so you don't have to learn it.
Which one is it? Learn or not?

Quote
You should really read the blog post of Selene I've link in an earlier post, it explains exactly what I mean. Code is much shorter and expressive when you use a C++ binding. Again: for a flexibility trade-off.
I read it long before this thread appeared. Selene is 10% feature complete, if that. Also, show me the C++ version. Unless there was a commit of VERY significant work, that adds upvalues to Selene in time between now and back when I downloaded it originally, it doesn't have them yet!

Quote
C++ version must be trivial.
Show the example code or go away with your 'claims'. If the way of the super C++ binding is so easy that using 4 methods is 'much' why did you not produce any so far to enlighten me?
Here is a C version, half of lines are setup required for other things, lines with x are 'dangerous' like a slightly untame little kitten.
int iwantthreeupvals(lua_State * L)
{
    const int a = luaL_checknumber(L, lua_upvalueindex(1));
    const int b = luaL_checknumber(L, lua_upvalueindex(2));
    const int c = luaL_checknumber(L, lua_upvalueindex(3));
    lua_pushnumber(L, a + b + c);
    return 1; //x
}

int main(int argc, char ** argv)
{
    lua_State * L = luaL_newstate();
    luaL_openlibs(L);
    lua_pushinteger(L, 10);
    lua_pushinteger(L, 20);
    lua_pushinteger(L, 30);
    lua_pushcclosure(L, &iwantthreeupvals, 3); //x
    lua_setglobal(L, "iwant");
    if(luaL_dostring(L, "print(iwant())"))
    {
        std::printf("%s\n", lua_tostring(L, -1));
    }
    lua_close(L);
}
 

Nexus - I'm tired of asking for clarifications of your convoluted statements, you have clear anti C, anti old C++ styles and anti C is ok to mix with C++ biases. Either you provide a clear answer, is C part of API good to know or not, and code examples of where C++ heavily beats C or you stop your raving against C API which had immense work put into it to become this clean.
LuaBridge is apparently not looked after anymore, Selene lacks a tonne of features, the blog post is at some times biased (but still more informative than your raving) and making code look longer in Lua version and omitting details. Slightly longer code in itself is not a downside, if the code is clearer and does one thing at a time as opposed to 5 that Selene likes to do. No other binding has been brough up by you or anyone. Probably none can compete against the fact that Lua:
0. has excellent documentation on itself, book PiL on the langauge and tons of tutorials that focus solely on the C API
1. is manatined
2. is developed (at a snail's pace but still, it is likely not going to die soon), and some bindings go back to 5.1 or 5.0 while Lua 5.3 is in sort of 'testing' right now
3. has a C API that is very clear and with superior feature set to most bindings when not overwhelmingly complex
4. has a C API that happens to largely overlap with one of fastest dynamic JITs - LuaJIT
Title: AW: Loading Game Data with Lua
Post by: eXpl0it3r on June 11, 2014, 07:57:38 am
I for one just don't like C APIs and I don't have to "proof" my likings. Is it baised? Yes. Do I care? No. :D

I can't believe to what extent you're going in defending the C API, but well everyone can spend their time and energy like they want. ;)
Title: Re: Loading Game Data with Lua
Post by: Laurent on June 11, 2014, 02:41:30 pm
If you have nothing more interesting to do than insulting each other in an endless war, please do it by PM. There were some interesting things in this discussion, too bad you have to be so much aggressive to say it.