The 'managed' keyword.

Started by Calin Leafshade, Thu 26/05/2011 14:27:26

Previous topic - Next topic

Calin Leafshade

So I recently discovered that AGS script allows you to make managed structs using this magic keyword however I am a little confused.

How can we have a managed struct with pointers if we have no way to actually make an instance of the struct? All other pointers in AGS have a static method which returns a pointer to a struct but in the script we can't do this because we would need someway of making a new struct to return which we can't.

The example Ryan Timothy posted in this thread (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=43593.msg580258#msg580258 ) seems to suggest that you can just declare the pointer and the engine will automatically create an empty instance of the struct.. is this how it works? because that seems a little odd to me considering that none of the other pointers behave like that.

I mean what is the intended use of this keyword and why isnt it mentioned in the literature?

Khris

As far as I understand the keyword allows to have pointers as struct members, not instances (pointers to custom structs, that is).
Thus you need to declare everything yourself:

Code: ags
managed struct str_guy {
  String Name;
  int value;
}

struct str_party {
  str_guy*guy[3];
}

str_guy Adam, Bert, Carl;
str_party players;

  players.guy[0] = Adam;
  players.guy[1] = Bert;
  players.guy[2] = Carl;


As soon as you have this, it's now save to do:

Code: ags
  player.guy[0].Name = "Adam";


Which is equivalent to

Code: ags
  Adam.Name = "Adam";


I was confused by this at first, too, but it does make sense; every object in the game has to be declared first.
Since structs don't have a Constructor, you can't create new instances dynamically (and you never could anyway).

monkey0506

Actually Khris as soon as you do:

Code: ags
str_guy Adam


You get an error:

QuoteCannot create instance of managed struct.

I don't know why Ryan seems to think that the code example he used there actually works. Because it doesn't. Try it. The compiler doesn't see a problem with it, but as soon as you actually execute the code you get a Null-pointer reference error.

The managed keyword is one of those, like attribute that is only intended for internal use, but for the compiler to work still has to be a valid part of the scripting language.

Engine plugins can actually create new managed types as well, and actually assign pointers to them. But you cannot do it in the script at all.

Being clever, I once thought that perhaps I would do this:

Code: ags
managed struct APointer
{
  int Data;
};

struct A extends APointer { };

APointer* GetPointer(this A*)
{
  return this;
}


Which also compiles fine (you're casting from a derived type to a base type), but as soon as you try to call that code you get another error:

QuotePointer cast failure: Object being pointed to is not in managed object pool

Which is essentially means to me that AGS's garbage collection doesn't expect the this pointer used within a member or extender method to be used outside of the context of the function. If the garbage collector could be notified that the pointer was being persisted, then I don't see why pointers to custom structs (in this sense) would be any different than pointers to the built-in or plugin-defined managed types.

Calin Leafshade

Thanks monkey, Thats basically what i thought would happen and why 'managed' seemed like a strange word to use if it worked at RT and Khris described.

I will continue using my utility plugin for custom structs.

Khris

#4
I forgot the asterisk, it still doesn't work though.
Weird, I could've sworn when I tested this yesterday it worked fine.

So when would you actually use the managed keyword?

Edit: I used Character*, not the custom struct.

monkey0506

Yes, Character pointers are fine. :P

The managed keyword isn't intended for general consumption at all. It has the following usages:

- Internally, for basically every complex data type that is still available for general consumption. (I think there might still be some of the old structures around here or there that aren't actually managed)

- Within an engine plugin, to define a new type that the end-user will define pointers to.

- Within a script module: to prevent the end-user from creating instances of a struct that is intended to be used statically.

And that's pretty much it as of right now.

I think RyanTimothy might actually have been mislead by a thread in which I used the managed keyword to create some pointers to a custom struct, never assign them a value, then use preprocessor macros to replace the null pointers with script aliases to existing instances of static struct instances of another custom struct. It's a fun and hackish thing to do, but it served the purpose that he wanted to achieve.

Calin Leafshade

i think its internal for defining things like dynamic sprites and stuff which have static constructor functions. You use that keyword in plugins when making custom objects for instance.

monkey0506

#7
It's internal for most data types: String, ViewFrame, Room, Game, Parser, Mouse, File, InventoryItem, Overlay, DynamicSprite, GUI, Label, Button, Slider, TextBox, InvWindow, ListBox, Character, Hotspot, Region, Dialog, Maths, DateTime, Object, DrawingSurface, and DialogOptionsRenderingInfo, but not for System (System.ViewportWidth, System.ViewportHeight, etc.) or GameState (game.* variables).

Some of the managed types you can't even assign pointers to (Room, Game, Parser, and Maths). Those are just defined as managed so that you can't create instances of them.

Note: I based this list off of 2.72 because the ROOMEDIT.CLB file was more readily at hand than the editor source (which has the autocomplete data, including these definitions). I added DrawingSurface and DialogOptionsRenderingInfo coz I knew those ones off-hand. I think that's all of them, but I could have forgotten something..(?)

Edit: I did forget, for AGS 3.2+ there's also the AudioChannel and AudioClip types which are also both managed.

Oh, and you only need to define a plugin-defined type as managed if you need pointers to it. Plugins can define non-managed types.

Wyz

As far as I know and correct me if I'm wrong, making a struct managed will introduce it to the managed object interface. This is callback interface that handles what happens when an AGS script deletes a managed object, or it wants to load or save it with save files. Basically it will result in a pointer to a data type internally defined. This datatype can only ever be created by a internally defined function (Like the Object.CreateSomething functions).
When creating plug-ins you probably need to create managed structs for objects  because there is likely some data representation you need to keep in a valid state.
Since in AGS script you can not do any dynamic memory management calling managed structs in modules is less useful.
Life is like an adventure without the pixel hunts.

monkey0506

Even if you need to keep some data introduced by a plugin "in a valid state" that doesn't inherently mean you need a pointer. Plugins only have to use managed types if they specifically need pointers to that type to be available. The same context could theoretically be applied to custom structs within, say, a script module. It would just require a change to the engine. The compiler wouldn't even have to be changed (presumably).

SMF spam blocked by CleanTalk