The current README is pretty terse, and reading API reference is a not pleasant way to learn any library. I propose to kidnap manual from any competing library (kagaya, selene, lua-intf to name a few), made a few edits to identifiers (and list of supported compilers) and put it into README. You may even combine parts kidnapeed here and there. Later Sol-specific features may be added, but it will be a good start.
I believe that now, when you are released a major stable version, lack of step-by-step tutorial is main barrier to wider Sol2 acceptance.
I'm considering doing this. Setting up a test repo where we make like a little shooter game using C++ and Lua with Sol as the glue.
... But my time. I have so very little.
If I get some free time, this will definitely be up there, though.
Greetings. I used to use Sol but could not figure out how it works (was too stupid back then XD but the manual wasn't very good either) and thus quickly switched over to Selene, since on its main page it had a much better tutorial/how-to-manual. However now I'm currently using Selene and thinking about switching to Sol2 (because it supports LuaJit, being able to switch between luajit and lua5.3 for comparison is quite nice) and i think has more features.
Personally, I'd suggest NOT writing a shooter game as a tutorial, at least for now. it would make things too complicated for people who just want to know how to use Sol2. Don't focus on giving a working example game, focus on explaining how to use Sol2 itself.
I'd suggest taking a look at Selenes main page
https://github.com/jeremyong/Selene
and do it like they did.
For tutorials, don't overcompliate things. Concentrate on single aspects with small dead-simple examples:
-this is how you create a Sol2 Lua state/start the connection between C++ and lua
-this is how you, from C++, create, access, write and read simple variables in Lua with Sol2
-this is how you, from C++, create, access/modify and remove tables in Lua with Sol2
-this is how you call C++ functions from Lua and use C++ return values in Lua
-this is how you call (table-nested) Lua functions from C++ and use Lua return values in C++
-this is how you register a C++ class and its functions in Lua with Sol2 and create an instance of that registered class it in Lua and then use it in Lua/C++
-this is how you register a C++ class instance and its functions in Lua with Sol2 and use it in Lua/C++
-this is how you run Lua-string-code directly in C++ (if possible with Sol2)
-this is how you send multi-value returns from Lua to C++ (if possible with Sol2)
-this is how you send multi-value returns from C++ to Lua (if possible with Sol2)
etc
Again, look at Selenes main page, i think that's the best way to show how a library gets used.
EDIT : Just found your page http://sol2.readthedocs.org/en/latest/
Looks really nice! That would be a good spot for tutorials.
However, i suggest adding a link to this page in your readme/main page of this repository.
I only found this page by accident by looking at the top of the page, where your link is barely noticeable. Most users look further down at the readme content for actual and important information. You should add a link to your page in the readme/repository main message part.
Righty-o, I'll put the tutorial and a big _Getting Started_ header in the readme when I do it.
Unfortunately, school school school school school school school school school school school school.
Haha, school is more important, i think everyone understands that. :)
I just skimmed through your example code files.
These are quite nice, they just have to be written out as real tutorial chapters.
The only thing i couldn't figure out from your examples are : You only show how to register a class (that we can then new() in Lua), but what if we want to register an already existing C++ class instance in Lua?
Objectclass someobject(); // how do i now register that class instance in lua?
Of course i could think of a way (creating a Lua table for it, putting a pointer to the instance in the table as reference if i want to return a pointer of it from Lua to C++, and adding references to class methods) but i think a clearly written "how-to" would be good.
Some additional things:
1)
How would you call functions in a table? I guess it's done this way (similar way to Selene), i guess both are valid methods to do it?
C++:
lua["table"]["nestedtable"]["function"]();
lua.script("table.nestedtable.function()");
The different methods how to do it should get mentioned a bit more, to show users the different possibilities they have for writing their code.
2)
Also, i think it should be mentioned for new users that in the case of using script_file() while the state already had another other files loaded doing another script_file() does not erase the stuff that already was loaded in the state earlier, but instead you can load as many lua script files are you like and only letting the sol::State get out of scope erases everything that has been script_file()-loaded so far. example :
C++
sol::state lua; //creates empty lua state
lua.script_file("test.lua"); // loads all the contents of "test.lua" into the lua state
lua.script_file("config.lua"); // does NOT erase the content loaded from test.lua,
//but instead config.lua gets loaded in addition to the content already in the lua state
I know that this is mostly common knowledge for many experienced users and it shouldn't be that high of a priority, but for beginners it's probably good to know (otherwise they start packing all their stuff in a single giant lua file ;-P ).
Other than the sparse documentation/tutorial, i really, really like it so far, i'll switch my current project to Sol2 as soon as possible.
Keep up the good work!
Ah, right, I don't go over that, but the answer is simple for registering your own stuff:
Doge dog{};
lua["dog"] = dog;
// OR: move semantics - will call move constructor if present instead
lua["dog"] = std::move( dog );
// Identical to above
lua.set("dog", dog);
lua.set("dog", std::move(dog));
This makes a copy/move, depending on what you ask for. If you want it to refer to something, whose memory you know won't die in C++,
Doge dog{}; // Kept alive somehow
// Later...
// The following stores a reference, and does not copy/move
lua["dog"] = &dog;
// Same as above: respects std::reference_wrapper
lua["dog"] = std::ref(dog);
// These two are identical to above
lua.set( "dog", &dog );
lua.set( "dog", std::ref( dog ) );
You can also set std::unique_ptrs (by moving them in) and std::shared_ptrs (copies or moves) and it will respect the semantics of each one, keeping them alive until the last / only reference of them dies (in the case of unique_ptr, when __gc is called. In the case of shared_ptr, by the regular reference counting rules).
They're all accessed the same way from lua, of course: no special reference/object syntax. Just use the dog:bark() and things.
As a buffer, I've updated the Readme to include a few pointers to places like examples and such. When I fix up the documentation I'll add some more in-your-face pointers to those as well.
The first little bits of a tutorial were written in this commit: https://github.com/ThePhD/sol2/commit/92c388e30a94ab2dee63eee07087402181a2f3dc
Which shows up here: http://sol2.readthedocs.org/en/latest/tutorial/getting-started.html (the page isn't linked from the document root yet).
Once this gets written up, we'll release 2.4...
Current progress: http://sol2.readthedocs.org/en/latest/tutorial/tutorial-top.html
I feel like there should be a "quick and dirty" page that reads more like Selene's readme, though...
Things that still need to be done:
sol::variadic_args, sol::this_state (the "transparent argument" types)sol::property (last one is part of usertype API)sol::readonly (for member variables part of the usertype and set_function APIs)stack::get/push/check overloads are provided for and what they do@Bulat-Ziganshin @Nava2 The hardcore documentation is done. Am going to update the readme and stuff soon. Let me know what you think.
As a reasonable place to ask, who owns a pointer returned to sol?
i.e.
lua["my_func"] = []() -> my_type* {
return new my_type();
};
Nobody: you've just created a dangling pointer. To fix:
lua["my_func"] = []() -> std::unique_ptr<my_type> {
return std::make_unique<my_type>();
};
Should that explicitly be written down in the documentation somewhere?
_0. it should mention first that
#include "sol.hpp"
should be included. and that sol is a header-only library (that don't need compilation). that's enough - we know how to run compiler and use git
_1. "set and get stuff" -> "set and get variables"
_2. "Some classes that have stuff to make it easier to look at lua semantics / be safe." phrase was hard to understand. what about something like "Retrieving types of Lua objects"
_3. in this code
some_class& myuserdata = lua["myuserdata"];
// myuserdata.some_variable = 20...
either second line should be "myuserdata = 20" or it needs more descriptions
_4. in this code
std::function<int()> stdfx = lua["f"];
sol::function fx = lua["f"];
int is_one = stdfx(1, 34.5, 3, "bark");
int is_also_one = fx();
seems that it should be stdfx() and fx(1, 34.5, 3, "bark")
_5. mistyped:
sol::bond
_6. this code:
int bark1 = def["y"]["bark"]; // 24
should be
def = ...
int bark1 = def["ghi"]["bark"]; // 50
note "ghi" and 50
Here
@Bulat-Ziganshin Thanks for the fixes. I think I got them all.
@Nava2 I added a section in the quick and dirty (at the bottom) for the point you brought up.
Thanks for all your help!
_1. 2.8 -> 4.8:
double is_2_8 = lua["g"](2.4, 2.4);
// is_2_8 == 2.8
_2. sol::bond -> bind? there are at least 2 occurences remained
_3. here:
lua.script("assert(dog.tailwag == 50)");
you don't defined ".tailwag" in Lua. section title says about metatables, but there is no code involving them
_4. i suggest renaming section "more userdata + usertypes" to "exporting C++ classes to Lua". it's less generic but easier to grok
_5. section titled "pointers" - seems that you mean that calls to my_func will create dangling pointers, not assignment itself? the text will be easier to grok if it will be stated explicitly
_6. overall, there are several mentions of owning. i suggest to combine them all into the sungle section at the end of tutorial, since it's imho most advanced topic. this inlcudes sections "pointers", "userdata + usertypes (metatables)", and this code (that cannot be groked at the beginning of tutorial):
// returns a plain reference
some_class& myuserdata = lua["myuserdata"];
// Modifies this in LUA VM AS WELL
// its a reference, not a copy!
myuserdata.some_variable = true;
so overall tutorial sequence will be "simple types - tables - functions - binding C++ classes - object ownership"
I guess I'll just name bond to tie instead, since nobody is going to know what bond is and it does look like a mispelling. :B
Okay, it's all fixed @Bulat-Ziganshin ! Thanks for all the help: I made sure to explicitly specify so does not take ownership of ANY pointers given to it, no matter how they're set / returned /cc @Nava2 .
sorry, i'm not native speaker and my English is mostly limited to tech papers :) anyway, using the same "tie" as in std is easier to remember
_1. you mistakenly renamed TWO sections to "C++ classes in Lua"
_2. both "mutiple returns" sections should probably go after "functions"
_3. i propose to replace first example with
#include "sol.h"
int main (int argc, char**argv) {
sol::state lua;
// open some common libraries
lua.open_libraries(sol::lib::base, sol::lib::package);
lua.script( "print('bark bark bark!')" );
}
because 1) i hate typing and prefer to copy-paste the full working example when starting to work through tutorial, and 2) i feel myself much more confident when i see complete ready-to-run first example of any new technology
I figure I'd do an in depth comment set too:
lua[]
// result == { 100, 200, 300 }
nil?Otherwise, I agree with @Bulat-Ziganshin! It looks pretty good.
Sol will push nil, yes. I updated the docs again, everything should be okay now!
i propose to reduce code to the following:
...
int bark1 = def["ghi"]["bark"];
int bark2 = lua["def"]["ghi"]["bark"];
// bark1 == bark2 == 50
int abcval1 = abc[0];
int abcval2 = ghi["woof"][0];
// abcval1 == abcval2 == 24
(dropping abcval_equal and bark_equal)
I can't find any tutorial about 'require' sol2 generated object in lua.
I naively do:
static int init() {
sol::state lua;
lua.new_usertype<Foo>("Foo", ...);
return 0;
}
static int initalized = init();
I produce a My_Object.so with that and in lua:
require ("My_Object")
But it doesn't work, so there should be another way.
Which one?
@alkino Opening a new issue is encouraged so I can properly keep track of your reports. I will move your request to a new issue and respond there.
Most helpful comment
Ah, right, I don't go over that, but the answer is simple for registering your own stuff:
This makes a copy/move, depending on what you ask for. If you want it to refer to something, whose memory you know won't die in C++,
You can also set
std::unique_ptrs (by moving them in) andstd::shared_ptrs (copies or moves) and it will respect the semantics of each one, keeping them alive until the last / only reference of them dies (in the case of unique_ptr, when __gc is called. In the case of shared_ptr, by the regular reference counting rules).They're all accessed the same way from lua, of course: no special reference/object syntax. Just use the
dog:bark()and things.