Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write a tutorial #36

Closed
Bulat-Ziganshin opened this issue Mar 17, 2016 · 25 comments
Closed

Write a tutorial #36

Bulat-Ziganshin opened this issue Mar 17, 2016 · 25 comments
Assignees

Comments

@Bulat-Ziganshin
Copy link

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.

@ThePhD
Copy link
Owner

ThePhD commented Mar 17, 2016

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.

@shohnwal
Copy link

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.

@ThePhD
Copy link
Owner

ThePhD commented Mar 21, 2016

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.

@shohnwal
Copy link

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.

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!

@ThePhD
Copy link
Owner

ThePhD commented Mar 21, 2016

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.

@ThePhD ThePhD self-assigned this Mar 21, 2016
@ThePhD ThePhD added this to the I Want A Red Panda milestone Mar 21, 2016
@ThePhD
Copy link
Owner

ThePhD commented Mar 21, 2016

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.

@ThePhD
Copy link
Owner

ThePhD commented Mar 30, 2016

The first little bits of a tutorial were written in this commit: 92c388e

Which shows up here: http://sol2.readthedocs.org/en/latest/tutorial/getting-started.html (the page isn't linked from the document root yet).

@ThePhD
Copy link
Owner

ThePhD commented Apr 7, 2016

Once this gets written up, we'll release 2.4...

@ThePhD
Copy link
Owner

ThePhD commented Apr 9, 2016

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...

@ThePhD
Copy link
Owner

ThePhD commented Apr 17, 2016

Things that still need to be done:

  • Setting/Getting Functions
  • Setting/Getting Userdata/Usertypes
  • Additional API documentation for sol::variadic_args, sol::this_state (the "transparent argument" types)
  • sol::property (last one is part of usertype API)
  • Additional API documentation for sol::readonly (for member variables part of the usertype and set_function APIs)
  • Specifically list all the types that stack::get/push/check overloads are provided for and what they do

@ThePhD
Copy link
Owner

ThePhD commented Apr 23, 2016

@Bulat-Ziganshin @Nava2 The hardcore documentation is done. Am going to update the readme and stuff soon. Let me know what you think.

@ThePhD ThePhD closed this as completed Apr 23, 2016
@Nava2
Copy link
Contributor

Nava2 commented Apr 23, 2016

As a reasonable place to ask, who owns a pointer returned to sol?

i.e.

lua["my_func"] = []() -> my_type* {
  return new my_type();
};

@ThePhD
Copy link
Owner

ThePhD commented Apr 23, 2016

Nobody: you've just created a dangling pointer. To fix:

lua["my_func"] = []() -> std::unique_ptr<my_type> {
  return std::make_unique<my_type>();
};

@ThePhD
Copy link
Owner

ThePhD commented Apr 23, 2016

Should that explicitly be written down in the documentation somewhere?

@Bulat-Ziganshin
Copy link
Author

Bulat-Ziganshin commented Apr 24, 2016

_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:

membver
sol::bond

_6. this code:

int bark1 = def["y"]["bark"];  // 24

should be

def = ...
int bark1 = def["ghi"]["bark"];  // 50

note "ghi" and 50

@ThePhD
Copy link
Owner

ThePhD commented Apr 24, 2016

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!

@Bulat-Ziganshin
Copy link
Author

Bulat-Ziganshin commented Apr 24, 2016

_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"

@ThePhD
Copy link
Owner

ThePhD commented Apr 24, 2016

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

@ThePhD
Copy link
Owner

ThePhD commented Apr 24, 2016

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 .

@Bulat-Ziganshin
Copy link
Author

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

@Nava2
Copy link
Contributor

Nava2 commented Apr 24, 2016

I figure I'd do an in depth comment set too:

  1. Link
    Remove the "Do it" the code is enough
  2. In "mutliple returns to lua" you have:
    lua[] // result == { 100, 200, 300 }
    This doesn't look like it was intentional.
  3. In Ownership, what's the behaviour if a nullptr is returned? Does sol set it to nil?

Otherwise, I agree with @Bulat-Ziganshin! It looks pretty good.

@ThePhD
Copy link
Owner

ThePhD commented Apr 24, 2016

Sol will push nil, yes. I updated the docs again, everything should be okay now!

@Bulat-Ziganshin
Copy link
Author

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)

@alkino
Copy link
Contributor

alkino commented Aug 1, 2017

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?

@ThePhD
Copy link
Owner

ThePhD commented Aug 1, 2017

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants