Thread Tools Display Modes
10/21/16, 02:17 AM   #1
Werewolf Finds Dragon
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 17
Any way to get the addon object that called a library function?

Okay, a lot of anxiety, here. I have so much social anxiety that it's not even funny so asking like this is hard. Usually I prefer figuring out my own problems, but I think I've come up against something that isn't actually possible.

So, what I've asked in the topic, or perhaps whether there's any way the two can communicate in any meaningful way? I'm guessing that the answer is no, since LibStub is a method of pointers rather than using unpack to replicate the library objects, and I completely understand why. I figured I'd ask though just in case there's any cleverness I hadn't considered.

Of course, I can't use self, since myAddon.libraryObject:libraryFunction() for example just returns libraryFunction as the only parent since it's only pointing at that. I don't believe there'd be any way to get any kind of inheritance there without passing the actual addon object through the function, which is what I'm trying to avoid. I have a function I'd like to use regularly, but without having to pass the addon object through every time.

So, is this possible? Or is this something I should give up on?
  Reply With Quote
10/21/16, 02:56 AM   #2
Randactyl
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 251
No worries! We're nice folk

So you want myAddon available in libraryFunction without calling libraryFunction(myAddon)?

If this is your own library, you could maybe build it such that you could take advantage of lexical scoping. If this is some other library, I think we're going to need some details in order to properly assess the situation.
  Reply With Quote
10/21/16, 06:28 PM   #3
Werewolf Finds Dragon
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 17
Thanks!

It's my own library, yes. I've just been fiddling with a utilities library for my addons. I have one for doing chat prints and I'm thinking of one to help out with events. I'm essentially throwing something similar to how WoW's Ace used to be in order to reduce reused code and redundant functions.

The thing is, however, is that I need to be able to call the addon object to be able to pull all of this off. I don't know how to do this. I did look into lexical methods but I'm not sure how to apply it to a library. I'm really rusty when it comes to code and I've always preferred small, manageable projects due to my anxiety.

Anyway, thanks for any info you can provide.
  Reply With Quote
10/21/16, 08:07 PM   #4
Ayantir
 
Ayantir's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 1,019
pass it as argument?..

Lua Code:
  1. local myAddon
  2. local LIB = LibStub("Library")
  3. LIB:Init(myAddon)

After if you need the addon object in your library, you maybe have a conception error. a lib should be addon independant.
  Reply With Quote
10/21/16, 09:02 PM   #5
Randactyl
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 251
I was going to suggest maybe passing it to init too.

You mentioned you had a print util. Maybe it would be enough to have a registration function you have to call initially which would generate and give the calling addon back a unique key. Then you pass the key as an argument whenever you need to. That's way more complicated and probably less effective than just passing the calling addon's namespace every time.

But Ayantir is right, libraries should be pretty independent of the code using them. Maybe the design should be revisited.
  Reply With Quote
10/21/16, 09:34 PM   #6
AssemblerManiac
AddOn Author - Click to view addons
Join Date: Jun 2014
Posts: 51
Some examples of how the library would reference it's owner might help.
  Reply With Quote
10/24/16, 07:08 AM   #7
Werewolf Finds Dragon
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 17
I was looking for an implementation of this, basically:

Code:
local addonFunction = debug.getinfo(2).func
local addonObjectName = debug.getupvalues(addonFunction, 1)
local addonObject = _G[addonObjectName]
local addonObjectValue = addonobject.myValue
print(addonObjectValue)
But it doesn't look like any implementation of that has made its way into ESO. Sorry to waste everyone's time with this.
  Reply With Quote
10/24/16, 07:53 AM   #8
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,577
Originally Posted by Werewolf Finds Dragon View Post
I was looking for an implementation of this, basically:

Code:
local addonFunction = debug.getinfo(2).func
local addonObjectName = debug.getupvalues(addonFunction, 1)
local addonObject = _G[addonObjectName]
local addonObjectValue = addonobject.myValue
print(addonObjectValue)
But it doesn't look like any implementation of that has made its way into ESO. Sorry to waste everyone's time with this.
Using debug functions in your regular code screams bad design.
Why not just pass the value to the function, or make your library return an instance (see ZO_Object) with your addonObject stored?
  Reply With Quote
10/24/16, 09:30 PM   #9
Werewolf Finds Dragon
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 17
Originally Posted by sirinsidiator View Post
Using debug functions in your regular code screams bad design.
Thinking outside the box is bad design? How? Why?? I don't understand how you could substantiate that reasonably or logically. It seems like a kneejerk reaction of traditionalism. The information is right there, it's easily obtainable, it's efficient, and it doesn't add any overhead versus other methods (I checked). I just can't deal with people who obsess over the outdated fundamentals of traditionalism and conventionalism. If those concepts hadn't been combated over a decade ago in WoW, we wouldn't have had Ace and we certainly wouldn't be using the kinds of libraries we're using today.

Sigh. I shouldn't have asked. Lesson learned. I thank everyone who was at least nice about it, though. I did mention my anxiety issues, after all. So I appreciate their input, even if what I was asking wasn't necessarily possible in ESO's implementation. I remember back in the day though that Cosmos coders told Ace coders what they were doing 'screamed bad design.' And look how that turned out. This will always happen, unfortunately. Come up with an original, unexpected implementation and someone will tell you it's 'bad design.' There's always someone.

Again, thanks to those who were nice about it.
  Reply With Quote
10/25/16, 06:27 AM   #10
sirinsidiator
 
sirinsidiator's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 1,577
Originally Posted by Werewolf Finds Dragon View Post
Thinking outside the box is bad design? How? Why?? I don't understand how you could substantiate that reasonably or logically. It seems like a kneejerk reaction of traditionalism. The information is right there, it's easily obtainable, it's efficient, and it doesn't add any overhead versus other methods (I checked). I just can't deal with people who obsess over the outdated fundamentals of traditionalism and conventionalism. If those concepts hadn't been combated over a decade ago in WoW, we wouldn't have had Ace and we certainly wouldn't be using the kinds of libraries we're using today.

Sigh. I shouldn't have asked. Lesson learned. I thank everyone who was at least nice about it, though. I did mention my anxiety issues, after all. So I appreciate their input, even if what I was asking wasn't necessarily possible in ESO's implementation. I remember back in the day though that Cosmos coders told Ace coders what they were doing 'screamed bad design.' And look how that turned out. This will always happen, unfortunately. Come up with an original, unexpected implementation and someone will tell you it's 'bad design.' There's always someone.

Again, thanks to those who were nice about it.
You should calm down a bit. I didn't mean to hurt your feelings and this has nothing to do with traditionalism. I also do not have anything against thinking outside of the box (which I do all the time).

There are three reasons why I said that it is bad design and you should not use functions that are explicitly marked for "debug" usage.

First, most of them generally have way worse performance than any "traditional" way to access the same information. Even if it makes it easier to implement something using the debug function, you should still consider taking the long way around in order to avoid any performance pitfalls that are not immediately noticable.

Secondly they make your code unnecessarily hard to understand and maintain for anyone who plans to fix it (including your future self) in the event that it breaks. It will be a nightmare to figure out what goes wrong, as they usually go around intentional limitations of the language in order to allow you to do what they are made for: debug your code.

Third, these functions quite often are not treated as part of a well-defined API and may change without much notice, breaking your program.

Hope this clears it up a bit.
  Reply With Quote
10/25/16, 06:38 AM   #11
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
I'm certain sirinsidiator was just trying to save you some trouble. Maybe we shouldn't have taken the example code literally, but it's really hard to not suggest a more solid design.

The whole debug module (except get/setfenv) is not available in ESO, so this discussion is kinda moot, but I'll go over the code anyway in order to explain the dangers. I assume the code was supposed to be inside libraryFunction, right?

Lua Code:
  1. local addonFunction = debug.getinfo(2).func
  2. local addonObjectName = debug.getupvalues(addonFunction, 1)
  3. -- I think what you meant was:
  4. local name, value = debug.getupvalue(addonFunction, 1)

There're a number of issues with this, though.
upvalues are *local* variables from *outside* scopes that are *used inside* a function.

Because they are locals, looking up _G[name] will give you some completely unrelated object/value/nil.
Second, there's absolutely no guarantee that upvalue #1 will be the calling addon's global table/name.

An example to illustrate:
Lua Code:
  1. function printupvalues()
  2.     local caller = debug.getinfo(2)
  3.     local i = 1
  4.     print(("caller=%s %s"):format(tostring(caller.name), tostring(caller.func)))
  5.     while true do
  6.         local name, val = debug.getupvalue(caller.func, i)
  7.         if name == nil then break end
  8.         print(("%4d: name=%s val=%s"):format(i, name, tostring(val)))
  9.         i = i + 1
  10.     end
  11. end
  12.  
  13. local a = 1
  14. local b = 2
  15. local c = 3
  16.  
  17. local function foo(x, y)
  18.     local d = 4
  19.     local e = 5
  20.     local function bar()
  21.         b = e + y
  22.         printupvalues()
  23.     end
  24.     a = d + x
  25.     printupvalues()
  26.     bar()
  27. end

foo's upvalues are: [1]=b, [2]=a -- see how they're in the order they're used in the function, not in the order they're declared!
bar's upvalues are: [1]=b, [2]=e, [3]=y

Notice that `c` is not among either function's upvalues, because it's not used anywhere.
`d` and `x` also aren't upvalues, because they're local in foo, and not used in bar.

Last edited by merlight : 10/25/16 at 06:41 AM.
  Reply With Quote
10/25/16, 07:20 AM   #12
AssemblerManiac
AddOn Author - Click to view addons
Join Date: Jun 2014
Posts: 51
Red face

Mr Wolfy

None of us will try to beat you down, or deliberately slam your work. We're all working for the same goal: Addons that extend ESO and can be maintained down the road. Please try and read the comments in a positive way (or at least as constructive), not a "you're an idiot" way.

If you're using debug functions as a primary part of your system and the person that takes over your addon maintenance (after you get hit by a bus, or decide to play the "next big thing" instead of eso) removes the debug calls to clean up the code, it might break something immediately and they'll notice, or they don't notice and a user finds it missing and gets all pissy about it (it's happened) and screams that the new author broke it (sorry for the run-on sentence, but it's nigh impossible to phrase that much better). We're all for thinking outside the box, but sometimes you just need to give that thinking a bit more thought.
  Reply With Quote
10/25/16, 01:18 PM   #13
Sasky
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 231
Can you provide more details about what you're trying to do? For example:
- How many variables/functions are you wanting from the addon table?
- How are you using them? Logging? Value manipulation? Output? etc.
Perhaps even provide your working code on pastebin or something.

Directly figuring out the addon table doesn't work. However, rather than stick to a rut of trying a particular method, if you provide more details of what you're trying to do the other people here can 'think outside the box' as well and come up with a different approach.
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » Any way to get the addon object that called a library function?

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off