Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Snarky on Sat 07/10/2017 14:08:18

Title: "Access a non-static member" error with static attribute
Post by: Snarky on Sat 07/10/2017 14:08:18
I have some Character* variables in a module script that I need to expose, but that I would like to stay read-only outside of the script. To that end, instead of just exporting the variables globally, I'm trying to put them as static attributes inside of a struct, with getters that return the script-local values:

Code (ags) Select
struct MyModule
{
  import static readonly attribute Character* ActiveCharacter;  // $AUTOCOMPLETESTATICONLY$
  import static Character* get_ActiveCharacter();               // $AUTOCOMPLETEIGNORE$
};


Implemented in the script as:

Code (ags) Select
Character* _activeCharacter;
static Character* MyModule::get_ActiveCharacter()
{
  return _activeCharacter;
}


However, when I try to actually refer to this character, I get a compilation error:

Code (ags) Select
  MyModule.ActiveCharacter.Say("Blah blah"); // Fails to compile

"must have an instance of the struct to access a non-static member"

It works (or at least, it doesn't throw a compilation error: I haven't been able to test it live) if I instead write:

Code (ags) Select
  Character* c = MyModule.ActiveCharacter
  c.Say("Blah blah");


However, that is massively less convenient, and makes the whole approach pretty much useless for me.

It seems to be related to this bug: http://www.adventuregamestudio.co.uk/forums/index.php?topic=32083.0

Is there any way around this or some way to fix it?
Title: Re: "Access a non-static member" error with static attribute
Post by: monkey0506 on Sun 15/10/2017 14:33:35
The only workaround presently is to not use static attributes.

struct MyModule_t // renamed, because we have to use an instance rather than statics
{
  import readonly attribute Character* ActiveCharacter;
};

import MyModule_t MyModule; // import the instance


MyModule_t MyModule;
export MyModule;

Character *_activeCharacter;

Character* get_ActiveCharacter(this MyModule_t*) // switched to extender just to avoid having to rely on $AUTOCOMPLETEIGNORE$, functionally the same
{
  return _activeCharacter;
}


MyModule.ActiveCharacter.Say("Blah blah");

This is the method I used in the latest ScrollingDialog module, for example, to achieve such feats as:

ScrollingDialog.ScrollArrows.Up.Padding.Bottom = 2;

It is a hassle to not be able to take full advantage of static attributes, but that's the current situation.
Title: Re: "Access a non-static member" error with static attribute
Post by: Snarky on Mon 16/10/2017 08:03:52
Thanks! That's essentially what I ended up doing, though your version is nicer, with the naming scheme mimicking a static class and the extender trick (I didn't know you could use extenders as attribute accessors).
Title: Re: "Access a non-static member" error with static attribute
Post by: monkey0506 on Mon 16/10/2017 14:03:02
Quote from: Snarky on Mon 16/10/2017 08:03:52the extender trick (I didn't know you could use extenders as attribute accessors).

Yeah, the way extender methods inject themselves means they are exactly the same as standard struct methods, even down to ridiculous and unnecessary definitions like:

import void Scream(this Character*); // imported using extender method syntax

void Character::Scream() // defined using standard method syntax
{
  this.Say("AHHHHHH!");
}


The engine and compiler don't make any distinction between the two once the extender is imported. This makes it particularly useful when attributes are involved, so you don't have to clutter up your struct definition with a bunch of hidden accessor methods. If you did have a static attribute, you can use either an instance extender or a static extender -- either one will work. :=
Title: Re: "Access a non-static member" error with static attribute
Post by: Crimson Wizard on Mon 16/10/2017 14:27:21
Quote from: Snarky on Mon 16/10/2017 08:03:52
I didn't know you could use extenders as attribute accessors.

BTW, this also makes it possible to declare "overriding" property accessors for structs that extend parent structs (Or so I remember).