    [NAME]
    ALL.daovm.interface.embedding

    [TITLE]
    Embedding Dao VM

    [DESCRIPTION]

     1   A Simple Example

     1.1   Initializing Dao Runtime

    Before doing anything with Dao as a library, one must call DaoInit() to initialize it
    first:

       1  // Initialize Dao:
       2  DaoVmSpace *vmspace = DaoInit( NULL );

    This function will return a DaoVmSpace object, which can be used to load Dao scripts or
    modules. It can optionally take a char* parameter, which is assumed to be the path and
    name of the application, and is used to add additional searching paths.

     1.2   Load A Script File

    Once you have a DaoVmSpace object, you can start to run Dao scripts or load Dao modules
    using this object. If you have a main script file and all you need to do is to run the
    file, you can simply call:

       1  // Load "myscript.dao":
       2  DaoVmSpace_Load( vmspace, "myscript.dao" );

     1.3   Finalize Dao Runtime

    After you are done with Dao, you may call the following function to make sure, Dao is
    properly finalized (waiting for unjoined threads to finish and the garbage collector to
    finish, and deallocating some internal data structures etc.).

       1  // Finalize (or Quit) Dao:
       2  DaoQuit();

     1.4   Putting These Codes Together

    Putting these codes together, embedding Dao can be as simple as,

       1  // Initialize Dao:
       2  DaoVmSpace *vmspace = DaoInit( NULL );
       3  // Load "myscript.dao":
       4  DaoVmSpace_Load( vmspace, "myscript.dao" );
       5  // Finalize (or Quit) Dao:
       6  DaoQuit();

     2   A Slightly More Advanced Example

    In Dao, each single script file is represented by one namespace object. And each
    namespace object has access to the public global constants and variables defined in the
    files that this file has loaded. To do anything interesting, one must obtain the
    namespace object for the file of interest.

     2.1   Obtaining The Namespace Object

    Following the above example, if you want to call a function defined in "myscript.dao"(or
    in the files it has loaded), you can simple store the returned namespace object in a
    variable,

       1  // Load "myscript.dao" and obtain the namespace object:
       2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );

     2.2   Obtaining The Function Object

    To find the function you want to call,

       1  // Find an object named "myfunction":
       2  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
       3  // Try to cast it to a function object:
       4  DaoRoutine *myfunc = DaoValue_CastRoutine( value );

    If "myfunction" is indeed a function, myfunc will not be NULL.

     2.3   Obtaining A Process Object

    Now to call the function, you will need another type of object: DaoProcess, which
    represents a virtual machine process and is responsible for executing scripts. You can
    directly call DaoProcess_New() to create a new process object, but normally the better
    to get a process object is to acquire it from a DaoVmSpace object:

       1  // Acquire a process object:
       2  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );

     2.4   Prepare Parameter Values

    Now suppose the function "myfunction" needs to take an integer as its first parameter and
    a string as the second. To call it, we will need to prepare parameters that can be passed
    to this function. The simplest way to do this is to use the data "factory" methods that
    are associated with the process type DaoProcess. Such methods are normally begin with
    DaoProcess_New. For example, to prepare an integer value and a string value, one can do,

       1  // Prepare an integer and a string:
       2  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
       3  DaoString  *svalue = DaoProcess_NewMBString( proc, "abc", -1 );

    The third parameter of DaoProcess_NewMBString() is the number of bytes in the C string,
    and a negative value can be used to indicate the C string is NULL terminated.

    To use these two new values in the parameter list to call "myfunction", you can do,

       1  DaoValue *params[2];
       2  params[0] = (DaoValue*) ivalue;
       3  params[1] = (DaoValue*) svalue;

    Or you can simply do,

       1  // Get the last two values:
       2  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );

    which will return last created two values in an array.

     2.5   Call The Function

    Now we are ready to call the function we obtained before with the prepared values,

       1  // Call the function:
       2  DaoProcess_Call( proc, myfunc, NULL, params, 2 );

    For class methods, a class instance object can be passed to this function as the third
    parameter, or it can be passed as the first value of params. Please note that, this
    function can handle overloaded functions automatically! So you do not need to do anything
    for that. This function will return zero on success, or other values with errors.

     2.6   Retrieve The Returned Value

    If the function returns a value, you can obtain it by,

       1  // Obtain the returned value:
       2  DaoValue *retvalue = DaoProcess_GetReturned( proc );

    If the returned value is supposed to be of certain type, you can cast it to that type by
    using one of the DaoValue_CastXXX() functions, or directly convert it to a proper C type
    by using one of the DaoValue_TryGetXXX() functions. For example, if "myfunction" returns
    an integer, you can get it by,

       1  // Get the integer return value
       2  daoint retint = DaoValue_TryGetInteger( retvalue );

     2.7   Release The Process Object

    After you have done with the process object, you can release it back the DaoVmSpace
    object,

       1  // Release the process:
       2  DaoVmSpace_ReleaseProcess( vmspace, proc );

    But if you want to use a process object frequently, you may simply retain it until you no
    longer need it. Then you may also need to the follow function to release the cached
    values

       1  // Pop the cached values:
       2  DaoProcess_PopValues( proc, 2 );

     2.8   Putting These Codes Together

       1  // Load "myscript.dao" and obtain the namespace object:
       2  DaoNamespace *nspace = DaoVmSpace_Load( vmspace, "myscript.dao" );
       3  // Find an object named "myfunction":
       4  DaoValue *value = DaoNamespace_FindData( nspace, "myfunction" );
       5  // Try to cast it to a function object:
       6  DaoRoutine *myfunc = DaoValue_CastRoutine( value );
       7
       8  // Acquire a process object:
       9  DaoProcess *proc = DaoVmSpace_AcquireProcess( vmspace );
      10
      11  // Prepare an integer and a string:
      12  DaoInteger *ivalue = DaoProcess_NewInteger( proc, 123 );
      13  DaoString  *svalue = DaoProcess_NewMBString( proc, "abc", -1 );
      14  // Get the last two values:
      15  DaoValue **params = DaoProcess_GetLastValues( proc, 2 );
      16
      17  // Call the function:
      18  DaoProcess_Call( proc, myfunc, NULL, params, 2 );
      19
      20  // Obtain the returned value:
      21  DaoValue *retvalue = DaoProcess_GetReturned( proc );
      22  // Get the integer return value
      23  daoint retint = DaoValue_TryGetInteger( retvalue );
      24
      25  // Release the process:
      26  DaoVmSpace_ReleaseProcess( vmspace, proc );