When there are multiple objects controlled by the same script implementation it may be favourable to use script classes, rather than global script functions. Using script classes each instance can have it's own set of variables within the class, contrary to the global functions that needs to rely on global variables to store persistent information.
Of course, it would be possible to duplicate the script modules, so that there is one module for each object instance, but that would be impose a rather big overhead for the application. Script classes don't have that overhead, as all instances share the same module, and thus the same bytecode and function ids, etc.
Before instantiating the script class you need to know which class to instantiate. Exactly how this is done depends on the application, but here are some suggestions.
If the application knows the name of the class, either hardcoded or from some configuration, the class type can easily be obtained by calling the module's GetTypeIdByDecl with the name of the class. The application can also choose to identify the class through some properties of the class, e.g. if the class implements a predefined interface. Then the application can enumerate the class types implemented in the script with GetObjectTypeByIndex and then examine the type through the asITypeInfo interface.
A third option, if you're using the script builder add-on, is to use the metadata to identify the class. If you choose this option, use the asIScriptModule to enumerate the declared types and then query the CScriptBuilder for their metadata.
Once the object type is known you create the instance by calling the class' factory function, passing it the necessary arguments, e.g. a pointer to the application object which the script class should be bound to. The factory function id is found by querying the asITypeInfo.
The factory function is called as a regular global function and returns a handle to the newly instanciated class.
Calling the methods of the script classes are similar to calling global functions except that you obtain the function id from the asITypeInfo, and you must set the object pointer along with the rest of the function arguments.
In order for the application to register a function that receives a script class it must first know the type. Of course, since the class is declared in the script it isn't possible to know the type before the script is compiled. Instead the application can register an interface with the engine. The function can then be registered to receive a handle to that interface.
The function that receives the interface should be implemented to take a pointer to an asIScriptObject.
If you don't want to use interfaces like this, then you may want to look into the variable argument type or the generic script handle add-on, which are ways that can be used to receive values and objects of which the type is not known beforehand.
Returning a script class from a registered function involves much of the same as receiving them. In order to register the function either an interface needs to be used, or the generic script handle add-on can be used.
This function can be registered as following: