Local Variables in MAXScript Exposed Functions

When writing functions that are exposed to MAXScript through and that use Value instances it is common practice to declare local variables using special macros found in maxscrpt/maxscrpt.h that protect them from the collector.

These macros will define a single local variable named vl (for 'v'alue 'l'ocals) that will have a number of fields corresponding to the number of arguments. Each field has the name passed to the macro, and is of type Value*.

For example:

two_typed_value_locals(Array* result, String* item);
vl.result = new Array (5);
vl.item = new String ("foo");
vl.result->append(vl.item);

There also typed versions of these macros:

There can be only one value_local declaration macro per C++ block.

Finalizing Local Variables

Value locals variables must be explicitly dismissed before the block is exited. One way to do this is with the macro: pop_value_locals(). This returns management of the Value variables to the collector.

However if you want to return one of the new values as the result, then this variable must continue to be protected from the garbage collector. You can use the macro return_value() to dismiss all local values and places the return value in a protected area.

In another case, you may have taken a value out of some rooted structure (say an array in a MAXScript global) and want to hand that back as a function result. To protect it against being collected if, for example, that rooted structure gets dropped, you can use the macro: return_protected() which protects the return value as does return_value() but doesn't dismiss any local values.

All functions in the MAXScript core that return potentially new values, including all the new operators, use one of these return value protection schemes. Since this means that a new value returned to you is safe until another function call or operation that might create another new value, you can forego the protection scheme in those cases in which you are immediately returning the new value.

One thing to note about these protected variables is that they are considered to be part of the root set and are scanned by the collector for internal references, so you only need to protect the top-level object if you are constructing some tree of values.