gilzoide / godot-lua-pluginscript

Godot PluginScript for the Lua language, currently based on LuaJIT's FFI
https://gilzoide.github.io/godot-lua-pluginscript/topics/README.md.html
MIT License
300 stars 21 forks source link

Self Converts Into a Table When Called From Function #7

Closed Jamtoad closed 2 years ago

Jamtoad commented 2 years ago

Hi, this is my first time ever posting an issue to GitHub, so I apologize if its not in the correct manner. I was recently working on some pathfinding and realized that "self" gets converted into a table if you reference it from a function that is being called that is not one of the built in functions.


Test.extends = "Navigation2D"

function Test:_ready()
    print(self)
    Test:Foo()
end

function Test:Foo()
    print(self)
end

return Test

In the example above, printing self from inside the _ready() function prints the correct game object, but if you print it from within the Foo() function it instead prints a table.

Thank you and have a wonderful day!

gilzoide commented 2 years ago

Hi there! Don't worry, there's no need to apologize ^^

In Lua, whenever you use method notation object:method(...), it is actually syntactic sugar for object.method(object, ...). In the same manner, defining a function as function object:method(...) end is syntactic sugar for function object.method(self, ...) end. Note here that self is just the name of the parameter and you can actually pass whatever value you want to it. If you called Test.Foo(1), the self parameter would have the value of 1, so that it would print 1, for example. This is just how Lua works.

In the code you posted, you are calling Test:Foo(), which in turn is the same as Test.Foo(Test). When Foo executes, the value passed to the parameter self is the table Test, which is not the same object as the variable self you have in _ready.

To call Foo with the same object as you have in _ready, you just have to call it as self:Foo(), which would be the same as self.Foo(self), instead of Test:Foo(). This way, the value passed to Foo's self parameter is the same self as you have in _ready. Since the variable self in _ready is an instance of your Test script, every method in Test will be available, including Foo and _ready, as well as all other methods from Navigation2D, which it extends.

Feel free to reply and/or ask more about this or other stuff, I'm glad to help! Have a wonderful day and year yourself =D


Just in case you're interested in behind the scenes, the script instance self is also a table, but one that defines a __tostring method that uses it's owner object for getting the string. That's why print(self) prints something like [Navigation2D:1234].

Jamtoad commented 2 years ago

Ooooooh, thats right! That makes a lot of sense! I used self:Function() in a couple of my other scripts and it worked fine. I was a little confused because it was working on other scripts I had written but not this one specifically. Thank you so much for the thorough, well written, quick response! I absolutely love this plugin, and I would love to support you and your work! I am going to setup an account on LibrePay.

gilzoide commented 2 years ago

I was a little confused because it was working on other scripts I had written but not this one specifically.

Hehe, that happens. More than we would like, unfortunately =P That reminds me of a quote that was something like: "I really hate this damned machine. It never does quite what I want, but only what I tell it".

Thank you so much for the thorough, well written, quick response!

No problem! The more information we can get, the best it is to understand what happened. We all learn together as well ^^

I absolutely love this plugin

I'm really glad to ~hear~ read that! That's what motivates working on this further. Well, that and I actually plan to use Lua + FFI in some Godot projects that I haven't started yet. Maybe this year, who knows?

and I would love to support you and your work

Thank you, I really appreciate that ^^ I've added a donation link from PayPal directly, might be easier for some people.