| AngelScript |

Loading...
Searching...
No Matches
Serialization

To serialize scripts the application needs to be able to iterate through all variables, and objects that have any relation to the script and store their content in a way that would allow it to be restored at a later time. For simple values this is trivial, but for objects and handles it becomes more complex as it is necessary to keep track of references between objects and internal structure of both classes defined by scripts and application registered types.

Iterating through the variables and members of objects is already described in the article about reflection, so this article will focus on the storing and restoring of values.

Look at the source code for the Serializer add-on for a sample implementation of serialization.

See also
  Hot reloading scripts

# Serialization of modules

To serialize the script modules you'll need to enumerate all the global variables and serialize each of them.

When deserializing the module, first compile it normally either from source script or by loading a pre-compiled byte code, except you first need to turn off initialization of global variables by turning off the engine property asEP_INIT_GLOBAL_VARS_AFTER_BUILD.

# Serialization of global variables

To serialize a global variable you'll need the name and namespace to use as the key for the variable, and then the type id and address of the variable. You get these with the methods asIScriptModule::GetGlobalVar and asIScriptModule::GetAddressOfGlobalVar. If the type id is for a primitive type, then the value can be stored as is. If it is a handle or reference you'll need to serialize the reference itself and the object it refers to. If the type id is an object type then serialize the object and its content.

To deserialize the global variable, you'll use the name and namespace to look it up, and then use GetAddressOfGlobalVar to get the address of the memory that needs to be restored with the serialized content.

# Serialization of objects

To serialize script objects you'll use the asIScriptObject interface to iterate over the members to store the content. Remember that objects can hold references to other objects and even to itself so it is important to keep track of object instances already serialized and just store a reference if the same object comes up again.

When deserializing the script objects you should first allocate the memory using asIScriptEngine::CreateUninitializedScriptObject so that the constructor is not executed, and then iterate over the members to restore their content.

For application registered types you obviously need to provide your own implementation as the script engine doesn't know the full content of the types and thus cannot provide an interface for serialization.

# Serialization of contexts

Serialization of a script context involves storing the full call stack with all the function calls, local variables, registers, etc. To do this you'll use the asIScriptContext interface.

- Use GetCallstackSize to get the size of the call stack
- For each call stack entry do:
  - Use GetCallStateRegisters to store the registers, i.e. program pointer, stack pointer, etc.
  - Use GetVarCount, GetVar, and GetAddressOfVar to store all local variables, including unnamed temporary variables
  - Use GetArgsOnStackCount and GetArgOnStack to store values pushed on the stack for a subsequent function call
- Use GetStateRegisters to store additional context registers

To deserialize a context follow these steps:

- Call StartDeserialization to tell the context that a deserialization will be done
- For each call stack entry previously stored do:
  - Call PushFunction to reserve space for a call stack entry
  - Call SetCallStateRegisters to restore the registers
  - Use GetVar and GetAddressOfVar to restore all local variables
  - Use GetArgOnStack to restore values pushed on the stack
- Call SetStateRegisters to restore additional context registers
- Call FinishDeserialization to conclude the serialization and allow the execution to resume

Todo:
  Add information on known restrictions, e.g. serialized contexts can only be restored on same cpu architecture, etc