Confused to hell about variable scoping throughout addons
8 replies, posted
Sorry if this has been answered somewhere else, but I could find anything in search (except about messaging between client/server which doesn't (yet) apply to me).
I'm creating quite a complex addon with various sweps and multiple files in the init directory. I'm putting data I need to share between lua files into tables within a single global table (so it acts like a namespace...right?) using _G["namespace"] = {} initially (since just namespace = {} didn't seem to do it for me either). It's first defined in an init.lua in addon/lua/autorun. There are other files in the same directory that I'm calling the namespace from, but I get 'nil' value errors when I try to access it. Is it because they're getting loaded before init.lua or something else? I'm getting the same error from stool files in the same addon. It's completely confused me.
Could someone give me a little overview of best practise for addon file location/loading and global namespacing?
You're probably not including the file where the variable is defined, so when it goes to look it up, it will just return nil because it's not in its scope. As long as the lua file with the variable's definition is included you should be able to share globals between the two files.
Thanks for the reply. That makes perfect sense, only I'm defining the global in init.lua (in lua/autorun) and then loading in other scripts from within that file. This isn't true of the stools however, but I assumed that init.lua was loaded first, and then everything else (stools included), so the global would already be defined before anything else was loaded.
A small part of my case:
init.lua - defines global, then loads drivers.lua from same directory.
drivers.lua - print(global.property) return 'nil'.
Perhaps the command I'm using to load them in is the problem? At the moment I'm using require (coming from a background of C-like languages) so that things are only loaded once. Should I be using a different command, or another command in drivers.lua to reference init.lua?
The function you should be using is "include":
[lua]include( 'drivers.lua' )[/lua]
Also, just because you're defining the global doesn't mean it's loaded by all lua files. It can only be accessed if the defining file is included, so if you're defining it in init.lua and accessing it in drivers.lua, you'll need to include init.lua in drivers.lua.
Ah...that's they key bit of info I was missing. Thanks alot Nerdeboy.
No problem!
It seems there's a part 2 to this problem. I've gotten to the stage where I can access the global from anywhere (I defined it in a shared file which I 'include' everywhere that references it...thanks again). The problem I'm seeing now appears to be that I can't write certain things to a child table of this global, which is defined in the same shared file as the global itself. If I print(global.child) from within the file I'm trying to write from, it returns the hashref to the table. I then get no complaints until a function tries to access these attachments...it tells me they're 'nil'. Checking with print(global.child.function) returns 'nil' as well when I run it from console. It seems like there's some trouble writing to the child table from a file that it wasn't defined in, and yet it works for the global. Is this not something I can do for non-globals, even if they are part of a global?
Apologies if I seem to be overcomplicating things, but my codebase is already getting so large that many different files/organising things into tables is becoming necessary.
Can you print(global.child) from the function or is that returning nil?
I was about to explain that both file and function scope had access to global.child, when something occurred to me...this one'll make you laugh (or possible cry). Every time I was including the shared lua file, I was overwriting this variable with a blank table (I only intended to initialize it once). It wasn't happening for the global because I'd already coded that not to "reinitialize" if it already existed. This is why I was using require rather than include originally, but it seems according the the (rather vague) wiki, one is for DLL etc., and the other is for Lua. Interesting...or have I got that completely wrong?
Anyway now I've got rid of this issue, I'm not even needing to include the shared global file in anything but the autorun/init.lua file (the whole load it all into shared memory thing that I was expecting but not seeing...my fault. Figures).
I'm seeing some smaller, but nonetheless annoying scope issues now when interacting with hooks. For example, I define a global.child variable that's just a string in the global table (which I can get at from anywhere). The really odd thing is I can read this variable from wherever, but when I try to write to it from within a TOOL:LeftClick function, the value doesn't change. If I try to write to it from anywhere else (even from a function called by one of my custom hooks), it works just fine. Do these TOOL:LeftClick functions have some sort of read only global scope? I'm pretty sure I've not done anything else stupid that could be causing this, but it's kind of a pain when I'm trying to assign things based on a STool's left click target.
Edit: I suspected and proved that I'm now getting problems between client/server side copies of things in this global...when I ran everything in the server "realm", I could get at everything. Now I just have to figure out what needs to run in the client, and what needs to run in the server...this is going to be fun.
Sorry, you need to Log In to post a reply to this thread.